summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuy Martin <gmsoft@gentoo.org>2004-05-30 01:35:27 +0000
committerGuy Martin <gmsoft@gentoo.org>2004-05-30 01:35:27 +0000
commit00d7ab5266c43fe80004dfaca688d2f9ee6b8ea0 (patch)
tree6103a0ab534b4d110e6478f7ef85401d7ab9fb08 /sys-devel/gdb
parentstable on x86 (only a tiny change from -r0) (Manifest recommit) (diff)
downloadgentoo-2-00d7ab5266c43fe80004dfaca688d2f9ee6b8ea0.tar.gz
gentoo-2-00d7ab5266c43fe80004dfaca688d2f9ee6b8ea0.tar.bz2
gentoo-2-00d7ab5266c43fe80004dfaca688d2f9ee6b8ea0.zip
Added hppa support to gdb-6.1. Marked ~hppa.
Diffstat (limited to 'sys-devel/gdb')
-rw-r--r--sys-devel/gdb/ChangeLog6
-rw-r--r--sys-devel/gdb/files/gdb-6.1-hppa.patch5816
-rw-r--r--sys-devel/gdb/gdb-6.1.ebuild3
3 files changed, 5823 insertions, 2 deletions
diff --git a/sys-devel/gdb/ChangeLog b/sys-devel/gdb/ChangeLog
index e0940ae35bb4..d428b306fe5a 100644
--- a/sys-devel/gdb/ChangeLog
+++ b/sys-devel/gdb/ChangeLog
@@ -1,6 +1,10 @@
# ChangeLog for sys-devel/gdb
# Copyright 2002-2004 Gentoo Technologies, Inc.; Distributed under the GPL v2
-# $Header: /var/cvsroot/gentoo-x86/sys-devel/gdb/ChangeLog,v 1.39 2004/05/28 16:29:29 tgall Exp $
+# $Header: /var/cvsroot/gentoo-x86/sys-devel/gdb/ChangeLog,v 1.40 2004/05/30 01:35:27 gmsoft Exp $
+
+ 30 May 2004; Guy Martin <gmsoft@gentoo.org> gdb-6.1.ebuild,
+ files/gdb-6.1-hppa.patch:
+ Added hppa support to gdb-6.1. Marked ~hppa.
28 May 2004; Tom Gall <tgall@gentoo.org> gdb-6.1.ebuild:
stable on ppc64 (with small patch)
diff --git a/sys-devel/gdb/files/gdb-6.1-hppa.patch b/sys-devel/gdb/files/gdb-6.1-hppa.patch
new file mode 100644
index 000000000000..d362eb92ed1a
--- /dev/null
+++ b/sys-devel/gdb/files/gdb-6.1-hppa.patch
@@ -0,0 +1,5816 @@
+diff -uNr gdb-6.1.orig/gdb/config/djgpp/fnchange.lst gdb-6.1/gdb/config/djgpp/fnchange.lst
+--- gdb-6.1.orig/gdb/config/djgpp/fnchange.lst 2004-05-29 19:34:06.045080792 +0000
++++ gdb-6.1/gdb/config/djgpp/fnchange.lst 2004-05-29 19:37:43.094084328 +0000
+@@ -232,6 +232,8 @@
+ @V@/gdb/testsuite/gdb.mi/mi2-var-display.exp @V@/gdb/testsuite/gdb.mi/mi2vardisplay.exp
+ @V@/gdb/amd64-linux-tdep.c @V@/gdb/amd64-ltdep.c
+ @V@/gdb/amd64-linux-nat.c @V@/gdb/amd64-lnat.c
++@V@/gdb/hppa-linux-tdep.c @V@/gdb/palnxtdep.c
++@V@/gdb/hppa-linux-nat.c @V@/gdb/palnxnat.c
+ @V@/include/ChangeLog-9103 @V@/include/ChangeLog.9103
+ @V@/include/coff/ChangeLog-9103 @V@/include/coff/ChangeLog.9103
+ @V@/include/elf/ChangeLog-9103 @V@/include/elf/ChangeLog.9103
+diff -uNr gdb-6.1.orig/gdb/config/pa/linux.mh gdb-6.1/gdb/config/pa/linux.mh
+--- gdb-6.1.orig/gdb/config/pa/linux.mh 1970-01-01 00:00:00.000000000 +0000
++++ gdb-6.1/gdb/config/pa/linux.mh 2004-05-29 19:37:43.097083872 +0000
+@@ -0,0 +1,9 @@
++# Host: Hewlett-Packard PA-RISC machine, running Linux
++XDEPFILES=
++XM_FILE= xm-linux.h
++NAT_FILE= nm-linux.h
++NATDEPFILES= infptrace.o inftarg.o fork-child.o corelow.o gcore.o \
++ core-regset.o hppa-linux-nat.o linux-proc.o \
++ proc-service.o thread-db.o lin-lwp.o linux-nat.o
++
++XM_CLIBS= -ldl -rdynamic
+diff -uNr gdb-6.1.orig/gdb/config/pa/linux.mt gdb-6.1/gdb/config/pa/linux.mt
+--- gdb-6.1.orig/gdb/config/pa/linux.mt 1970-01-01 00:00:00.000000000 +0000
++++ gdb-6.1/gdb/config/pa/linux.mt 2004-05-29 19:37:43.099083568 +0000
+@@ -0,0 +1,3 @@
++# Target: HP PA-RISC running Linux
++TDEPFILES= hppa-tdep.o hppa-linux-tdep.o glibc-tdep.o solib.o solib-svr4.o
++TM_FILE=tm-hppa.h
+diff -uNr gdb-6.1.orig/gdb/config/pa/nm-linux.h gdb-6.1/gdb/config/pa/nm-linux.h
+--- gdb-6.1.orig/gdb/config/pa/nm-linux.h 1970-01-01 00:00:00.000000000 +0000
++++ gdb-6.1/gdb/config/pa/nm-linux.h 2004-05-29 19:37:43.101083264 +0000
+@@ -0,0 +1,56 @@
++/* Native support for GNU/Linux, for GDB, the GNU debugger.
++ Copyright (C) 2004 Free Software Foundation, Inc.
++
++ This file is part of GDB.
++
++ This program is free software; you can redistribute it and/or modify
++ it under the terms of the GNU General Public License as published by
++ the Free Software Foundation; either version 2 of the License, or
++ (at your option) any later version.
++
++ This program is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU General Public License for more details.
++
++ You should have received a copy of the GNU General Public License
++ along with this program; if not, write to the Free Software
++ Foundation, Inc., 59 Temple Place - Suite 330,
++ Boston, MA 02111-1307, USA. */
++
++#ifndef PA_NM_LINUX_H
++#define PA_NM_LINUX_H
++
++#include "config/nm-linux.h"
++
++#define U_REGS_OFFSET 0
++
++#define CANNOT_FETCH_REGISTER(regno) pa_cannot_fetch_register(regno)
++extern int pa_cannot_fetch_register (int regno);
++
++#define CANNOT_STORE_REGISTER(regno) pa_cannot_store_register(regno)
++extern int pa_cannot_store_register (int regno);
++
++#define HAVE_STEPPABLE_WATCHPOINT 1
++#define STOPPED_BY_WATCHPOINT(W) \
++ pa_linux_stopped_by_watchpoint (PIDGET(inferior_ptid))
++extern CORE_ADDR pa_linux_stopped_by_watchpoint (int);
++
++#define target_insert_watchpoint(addr, len, type) \
++ pa_linux_insert_watchpoint (PIDGET(inferior_ptid), addr, len, type)
++extern int pa_linux_insert_watchpoint (int pid, CORE_ADDR addr,
++ int len, int rw);
++
++#define target_remove_watchpoint(addr, len, type) \
++ pa_linux_remove_watchpoint (PIDGET(inferior_ptid), addr, len)
++extern int pa_linux_remove_watchpoint (int pid, CORE_ADDR addr, int len);
++
++/* Hardware watchpoints */
++
++#define TARGET_HAS_HARDWARE_WATCHPOINTS
++
++#define TARGET_CAN_USE_HARDWARE_WATCHPOINT(type, cnt, ot) \
++ (type == bp_hardware_watchpoint)
++
++#endif
++
+diff -uNr gdb-6.1.orig/gdb/config/pa/tm-hppa.h gdb-6.1/gdb/config/pa/tm-hppa.h
+--- gdb-6.1.orig/gdb/config/pa/tm-hppa.h 2004-05-29 19:34:06.251049480 +0000
++++ gdb-6.1/gdb/config/pa/tm-hppa.h 2004-05-29 19:48:49.432785448 +0000
+@@ -26,9 +26,6 @@
+
+ #include "regcache.h"
+
+-/* Wonder if this is correct? Should be using push_dummy_call(). */
+-#define DEPRECATED_DUMMY_WRITE_SP(SP) deprecated_write_sp (SP)
+-
+ #define GDB_MULTI_ARCH 1
+
+ /* Hack, get around problem with including "arch-utils.h". */
+@@ -62,6 +59,8 @@
+ other r registers. */
+ #define FLAGS_REGNUM 0 /* Various status flags */
+ #define RP_REGNUM 2 /* return pointer */
++#define HPPA_FP_REGNUM 3 /* The ABI's frame pointer, when used */
++#define HPPA_SP_REGNUM 30 /* Stack pointer. */
+ #define SAR_REGNUM 32 /* Shift Amount Register */
+ #define IPSW_REGNUM 41 /* Interrupt Processor Status Word */
+ #define PCOQ_HEAD_REGNUM 33 /* instruction offset queue head */
+@@ -76,6 +75,7 @@
+ #define CCR_REGNUM 54 /* Coprocessor Configuration Register */
+ #define TR0_REGNUM 57 /* Temporary Registers (cr24 -> cr31) */
+ #define CR27_REGNUM 60 /* Base register for thread-local storage, cr27 */
++#define HPPA_FP0_REGNUM 64 /* First floating-point. */
+ #define FP4_REGNUM 72
+
+ #define ARG0_REGNUM 26 /* The first argument of a callee. */
+@@ -93,12 +93,6 @@
+ (buf)[sizeof(CORE_ADDR) -1] &= ~0x3; \
+ } while (0)
+
+-/* Define DEPRECATED_DO_REGISTERS_INFO() to do machine-specific
+- formatting of register dumps. */
+-
+-#define DEPRECATED_DO_REGISTERS_INFO(_regnum, fp) pa_do_registers_info (_regnum, fp)
+-extern void pa_do_registers_info (int, int);
+-
+ /* PA specific macro to see if the current instruction is nullified. */
+ #ifndef INSTRUCTION_NULLIFIED
+ extern int hppa_instruction_nullified (void);
+@@ -107,104 +101,6 @@
+
+ #define INSTRUCTION_SIZE 4
+
+-/* This sequence of words is the instructions
+-
+- ; Call stack frame has already been built by gdb. Since we could be calling
+- ; a varargs function, and we do not have the benefit of a stub to put things in
+- ; the right place, we load the first 4 word of arguments into both the general
+- ; and fp registers.
+- call_dummy
+- ldw -36(sp), arg0
+- ldw -40(sp), arg1
+- ldw -44(sp), arg2
+- ldw -48(sp), arg3
+- ldo -36(sp), r1
+- fldws 0(0, r1), fr4
+- fldds -4(0, r1), fr5
+- fldws -8(0, r1), fr6
+- fldds -12(0, r1), fr7
+- ldil 0, r22 ; FUNC_LDIL_OFFSET must point here
+- ldo 0(r22), r22 ; FUNC_LDO_OFFSET must point here
+- ldsid (0,r22), r4
+- ldil 0, r1 ; SR4EXPORT_LDIL_OFFSET must point here
+- ldo 0(r1), r1 ; SR4EXPORT_LDO_OFFSET must point here
+- ldsid (0,r1), r20
+- combt,=,n r4, r20, text_space ; If target is in data space, do a
+- ble 0(sr5, r22) ; "normal" procedure call
+- copy r31, r2
+- break 4, 8
+- mtsp r21, sr0
+- ble,n 0(sr0, r22)
+- text_space ; Otherwise, go through _sr4export,
+- ble (sr4, r1) ; which will return back here.
+- stw r31,-24(r30)
+- break 4, 8
+- mtsp r21, sr0
+- ble,n 0(sr0, r22)
+- nop ; To avoid kernel bugs
+- nop ; and keep the dummy 8 byte aligned
+-
+- The dummy decides if the target is in text space or data space. If
+- it's in data space, there's no problem because the target can
+- return back to the dummy. However, if the target is in text space,
+- the dummy calls the secret, undocumented routine _sr4export, which
+- calls a function in text space and can return to any space. Instead
+- of including fake instructions to represent saved registers, we
+- know that the frame is associated with the call dummy and treat it
+- specially.
+-
+- The trailing NOPs are needed to avoid a bug in HPUX, BSD and OSF1
+- kernels. If the memory at the location pointed to by the PC is
+- 0xffffffff then a ptrace step call will fail (even if the instruction
+- is nullified).
+-
+- The code to pop a dummy frame single steps three instructions
+- starting with the last mtsp. This includes the nullified "instruction"
+- following the ble (which is uninitialized junk). If the
+- "instruction" following the last BLE is 0xffffffff, then the ptrace
+- will fail and the dummy frame is not correctly popped.
+-
+- By placing a NOP in the delay slot of the BLE instruction we can be
+- sure that we never try to execute a 0xffffffff instruction and
+- avoid the kernel bug. The second NOP is needed to keep the call
+- dummy 8 byte aligned. */
+-
+-#define CALL_DUMMY {0x4BDA3FB9, 0x4BD93FB1, 0x4BD83FA9, 0x4BD73FA1,\
+- 0x37C13FB9, 0x24201004, 0x2C391005, 0x24311006,\
+- 0x2C291007, 0x22C00000, 0x36D60000, 0x02C010A4,\
+- 0x20200000, 0x34210000, 0x002010b4, 0x82842022,\
+- 0xe6c06000, 0x081f0242, 0x00010004, 0x00151820,\
+- 0xe6c00002, 0xe4202000, 0x6bdf3fd1, 0x00010004,\
+- 0x00151820, 0xe6c00002, 0x08000240, 0x08000240}
+-
+-#define REG_PARM_STACK_SPACE 16
+-
+-/* If we've reached a trap instruction within the call dummy, then
+- we'll consider that to mean that we've reached the call dummy's
+- end after its successful completion. */
+-#define DEPRECATED_CALL_DUMMY_HAS_COMPLETED(pc, sp, frame_address) \
+- (DEPRECATED_PC_IN_CALL_DUMMY((pc), (sp), (frame_address)) && \
+- (read_memory_integer((pc), 4) == BREAKPOINT32))
+-
+-/* Insert the specified number of args and function address into a
+- call sequence of the above form stored at DUMMYNAME.
+-
+- On the hppa we need to call the stack dummy through $$dyncall.
+- Therefore our version of DEPRECATED_FIX_CALL_DUMMY takes an extra
+- argument, real_pc, which is the location where gdb should start up
+- the inferior to do the function call. */
+-
+-/* FIXME: brobecker 2002-12-26. This macro is going to cause us some
+- problems before we can go to multiarch partial as it has been
+- diverted on HPUX to return the value of the PC! */
+-/* NOTE: cagney/2003-05-03: This has been replaced by push_dummy_code.
+- Hopefully that has all the parameters HP/UX needs. */
+-#define DEPRECATED_FIX_CALL_DUMMY hppa_fix_call_dummy
+-extern CORE_ADDR hppa_fix_call_dummy (char *, CORE_ADDR, CORE_ADDR, int,
+- struct value **, struct type *, int);
+-
+-#define GDB_TARGET_IS_HPPA
+-
+ /*
+ * Unwind table and descriptor.
+ */
+diff -uNr gdb-6.1.orig/gdb/config/pa/tm-hppa64.h gdb-6.1/gdb/config/pa/tm-hppa64.h
+--- gdb-6.1.orig/gdb/config/pa/tm-hppa64.h 2004-05-29 19:34:06.252049328 +0000
++++ gdb-6.1/gdb/config/pa/tm-hppa64.h 2004-05-29 19:48:49.436784840 +0000
+@@ -57,81 +57,9 @@
+
+ /* jimb: omitted dynamic linking stuff here */
+
+-/* This sequence of words is the instructions
+-
+-; Call stack frame has already been built by gdb. Since we could be calling
+-; a varargs function, and we do not have the benefit of a stub to put things in
+-; the right place, we load the first 8 word of arguments into both the general
+-; and fp registers.
+-call_dummy
+- nop
+- copy %r4,%r29
+- copy %r5,%r22
+- copy %r6,%r27
+- fldd -64(0,%r29),%fr4
+- fldd -56(0,%r29),%fr5
+- fldd -48(0,%r29),%fr6
+- fldd -40(0,%r29),%fr7
+- fldd -32(0,%r29),%fr8
+- fldd -24(0,%r29),%fr9
+- fldd -16(0,%r29),%fr10
+- fldd -8(0,%r29),%fr11
+- copy %r22,%r1
+- ldd -64(%r29), %r26
+- ldd -56(%r29), %r25
+- ldd -48(%r29), %r24
+- ldd -40(%r29), %r23
+- ldd -32(%r29), %r22
+- ldd -24(%r29), %r21
+- ldd -16(%r29), %r20
+- bve,l (%r1),%r2
+- ldd -8(%r29), %r19
+- break 4, 8
+- mtsp %r21, %sr0
+- ble 0(%sr0, %r22)
+- nop
+-*/
+-
+-/* Call dummys are sized and written out in word sized hunks. So we have
+- to pack the instructions into words. Ugh. */
+-#undef CALL_DUMMY
+-#define CALL_DUMMY {0x08000240349d0000LL, 0x34b6000034db0000LL, \
+- 0x53a43f8353a53f93LL, 0x53a63fa353a73fb3LL,\
+- 0x53a83fc353a93fd3LL, 0x2fa1100a2fb1100bLL,\
+- 0x36c1000053ba3f81LL, 0x53b93f9153b83fa1LL,\
+- 0x53b73fb153b63fc1LL, 0x53b53fd10fa110d4LL,\
+- 0xe820f0000fb110d3LL, 0x0001000400151820LL,\
+- 0xe6c0000008000240LL}
+-
+-/* The PA64 ABI reserves 64 bytes of stack space for outgoing register
+- parameters. */
+-#undef REG_PARM_STACK_SPACE
+-#define REG_PARM_STACK_SPACE 64
+-
+-/* Use the 64-bit calling conventions designed for the PA2.0 in wide mode. */
+-#define PA20W_CALLING_CONVENTIONS
+-
+ #undef FUNC_LDIL_OFFSET
+ #undef FUNC_LDO_OFFSET
+ #undef SR4EXPORT_LDIL_OFFSET
+ #undef SR4EXPORT_LDO_OFFSET
+
+-#undef FRAME_SAVED_PC_IN_SIGTRAMP
+-extern void hppa64_hpux_frame_saved_pc_in_sigtramp (struct frame_info *fi,
+- CORE_ADDR *tmp);
+-#define FRAME_SAVED_PC_IN_SIGTRAMP(FRAME, TMP) \
+- hppa64_hpux_frame_saved_pc_in_sigtramp (FRAME, TMP)
+-
+-#undef FRAME_BASE_BEFORE_SIGTRAMP
+-extern void hppa64_hpux_frame_base_before_sigtramp (struct frame_info *fi,
+- CORE_ADDR *tmp);
+-#define FRAME_BASE_BEFORE_SIGTRAMP(FRAME, TMP) \
+- hppa64_hpux_frame_base_before_sigtramp (FRAME, TMP)
+-
+-#undef FRAME_FIND_SAVED_REGS_IN_SIGTRAMP
+-extern void hppa64_hpux_frame_find_saved_regs_in_sigtramp
+- (struct frame_info *fi, CORE_ADDR *fsr);
+-#define FRAME_FIND_SAVED_REGS_IN_SIGTRAMP(FRAME, FSR) \
+- hppa64_hpux_frame_find_saved_regs_in_sigtramp (FRAME, FSR)
+-
+ /* jimb: omitted purify call support */
+diff -uNr gdb-6.1.orig/gdb/config/pa/tm-hppah.h gdb-6.1/gdb/config/pa/tm-hppah.h
+--- gdb-6.1.orig/gdb/config/pa/tm-hppah.h 2004-05-29 19:34:06.253049176 +0000
++++ gdb-6.1/gdb/config/pa/tm-hppah.h 2004-05-29 19:48:49.438784536 +0000
+@@ -36,21 +36,6 @@
+ #include "somsolib.h"
+ #endif
+
+-extern void hppa32_hpux_frame_saved_pc_in_sigtramp (struct frame_info *fi,
+- CORE_ADDR *tmp);
+-#define FRAME_SAVED_PC_IN_SIGTRAMP(FRAME, TMP) \
+- hppa32_hpux_frame_saved_pc_in_sigtramp (FRAME, TMP)
+-
+-extern void hppa32_hpux_frame_base_before_sigtramp (struct frame_info *fi,
+- CORE_ADDR *tmp);
+-#define FRAME_BASE_BEFORE_SIGTRAMP(FRAME, TMP) \
+- hppa32_hpux_frame_base_before_sigtramp (FRAME, TMP)
+-
+-extern void hppa32_hpux_frame_find_saved_regs_in_sigtramp
+- (struct frame_info *fi, CORE_ADDR *fsr);
+-#define FRAME_FIND_SAVED_REGS_IN_SIGTRAMP(FRAME, FSR) \
+- hppa32_hpux_frame_find_saved_regs_in_sigtramp (FRAME, FSR)
+-
+ /* For HP-UX on PA-RISC we have an implementation
+ for the exception handling target op (in hppa-tdep.c) */
+ #define CHILD_ENABLE_EXCEPTION_CALLBACK
+diff -uNr gdb-6.1.orig/gdb/config/pa/xm-linux.h gdb-6.1/gdb/config/pa/xm-linux.h
+--- gdb-6.1.orig/gdb/config/pa/xm-linux.h 1970-01-01 00:00:00.000000000 +0000
++++ gdb-6.1/gdb/config/pa/xm-linux.h 2004-05-29 19:37:43.103082960 +0000
+@@ -0,0 +1,31 @@
++/* Host-dependent definitions for the hppa-linux.
++
++ Copyright 2004 Free Software Foundation, Inc.
++
++ This file is part of GDB.
++
++ This program is free software; you can redistribute it and/or modify
++ it under the terms of the GNU General Public License as published by
++ the Free Software Foundation; either version 2 of the License, or
++ (at your option) any later version.
++
++ This program is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU General Public License for more details.
++
++ You should have received a copy of the GNU General Public License
++ along with this program; if not, write to the Free Software
++ Foundation, Inc., 59 Temple Place - Suite 330,
++ Boston, MA 02111-1307, USA. */
++
++#ifndef XM_HPPA_LINUX_H
++#define XM_HPPA_LINUX_H
++
++#include "floatformat.h"
++
++#define HOST_FLOAT_FORMAT &floatformat_ieee_single_big
++#define HOST_DOUBLE_FORMAT &floatformat_ieee_double_big
++#define HOST_LONG_DOUBLE_FORMAT &floatformat_ieee_double_big
++
++#endif /* xm-linux.h */
+diff -uNr gdb-6.1.orig/gdb/configure.host gdb-6.1/gdb/configure.host
+--- gdb-6.1.orig/gdb/configure.host 2004-05-29 19:34:05.288195856 +0000
++++ gdb-6.1/gdb/configure.host 2004-05-29 19:37:43.106082504 +0000
+@@ -48,6 +48,7 @@
+ hppa*64*-*-hpux11*) gdb_host=hpux11w ;;
+ hppa*-*-hpux11*) gdb_host=hpux11 ;;
+ hppa*-*-hpux*) gdb_host=hppahpux ;;
++hppa*-*-linux*) gdb_host=linux ;;
+
+ i[34567]86-ncr-*) gdb_host=ncr3000 ;;
+ i[34567]86-*-dgux*) gdb_host=i386v4 ;;
+diff -uNr gdb-6.1.orig/gdb/configure.tgt gdb-6.1/gdb/configure.tgt
+--- gdb-6.1.orig/gdb/configure.tgt 2004-05-29 19:34:05.291195400 +0000
++++ gdb-6.1/gdb/configure.tgt 2004-05-29 19:37:43.109082048 +0000
+@@ -74,6 +74,7 @@
+ hppa*64*-*-hpux11*) gdb_target=hppa64 ;;
+ hppa*-*-hpux*) gdb_target=hppahpux ;;
+ hppa*-*-hiux*) gdb_target=hppahpux ;;
++hppa*-*-linux*) gdb_target=linux ;;
+ hppa*-*-*) gdb_target=hppa ;;
+
+ i[34567]86-ncr-*) gdb_target=ncr3000 ;;
+diff -uNr gdb-6.1.orig/gdb/hppa-hpux-tdep.c gdb-6.1/gdb/hppa-hpux-tdep.c
+--- gdb-6.1.orig/gdb/hppa-hpux-tdep.c 2004-05-29 19:34:05.464169104 +0000
++++ gdb-6.1/gdb/hppa-hpux-tdep.c 2004-05-29 19:49:00.099163912 +0000
+@@ -24,11 +24,32 @@
+ #include "osabi.h"
+ #include "gdb_string.h"
+ #include "frame.h"
++#include "symtab.h"
++#include "objfiles.h"
++#include "inferior.h"
++#include "infcall.h"
++
++#include <dl.h>
++#include <machine/save_state.h>
+
+ /* Forward declarations. */
+ extern void _initialize_hppa_hpux_tdep (void);
+ extern initialize_file_ftype _initialize_hppa_hpux_tdep;
+
++typedef struct
++ {
++ struct minimal_symbol *msym;
++ CORE_ADDR solib_handle;
++ CORE_ADDR return_val;
++ }
++args_for_find_stub;
++
++/* This is declared in symtab.c; set to 1 in hp-symtab-read.c */
++extern int hp_som_som_object_present;
++
++/* In breakpoint.c */
++extern int exception_catchpoints_are_fragile;
++
+ /* FIXME: brobecker 2002-12-25. The following functions will eventually
+ become static, after the multiarching conversion is done. */
+ int hppa_hpux_pc_in_sigtramp (CORE_ADDR pc, char *name);
+@@ -148,10 +169,560 @@
+ }
+ }
+
++/* Exception handling support for the HP-UX ANSI C++ compiler.
++ The compiler (aCC) provides a callback for exception events;
++ GDB can set a breakpoint on this callback and find out what
++ exception event has occurred. */
++
++/* The name of the hook to be set to point to the callback function */
++static char HP_ACC_EH_notify_hook[] = "__eh_notify_hook";
++/* The name of the function to be used to set the hook value */
++static char HP_ACC_EH_set_hook_value[] = "__eh_set_hook_value";
++/* The name of the callback function in end.o */
++static char HP_ACC_EH_notify_callback[] = "__d_eh_notify_callback";
++/* Name of function in end.o on which a break is set (called by above) */
++static char HP_ACC_EH_break[] = "__d_eh_break";
++/* Name of flag (in end.o) that enables catching throws */
++static char HP_ACC_EH_catch_throw[] = "__d_eh_catch_throw";
++/* Name of flag (in end.o) that enables catching catching */
++static char HP_ACC_EH_catch_catch[] = "__d_eh_catch_catch";
++/* The enum used by aCC */
++typedef enum
++ {
++ __EH_NOTIFY_THROW,
++ __EH_NOTIFY_CATCH
++ }
++__eh_notification;
++
++/* Is exception-handling support available with this executable? */
++static int hp_cxx_exception_support = 0;
++/* Has the initialize function been run? */
++int hp_cxx_exception_support_initialized = 0;
++/* Similar to above, but imported from breakpoint.c -- non-target-specific */
++extern int exception_support_initialized;
++/* Address of __eh_notify_hook */
++static CORE_ADDR eh_notify_hook_addr = 0;
++/* Address of __d_eh_notify_callback */
++static CORE_ADDR eh_notify_callback_addr = 0;
++/* Address of __d_eh_break */
++static CORE_ADDR eh_break_addr = 0;
++/* Address of __d_eh_catch_catch */
++static CORE_ADDR eh_catch_catch_addr = 0;
++/* Address of __d_eh_catch_throw */
++static CORE_ADDR eh_catch_throw_addr = 0;
++/* Sal for __d_eh_break */
++static struct symtab_and_line *break_callback_sal = 0;
++
++/* Code in end.c expects __d_pid to be set in the inferior,
++ otherwise __d_eh_notify_callback doesn't bother to call
++ __d_eh_break! So we poke the pid into this symbol
++ ourselves.
++ 0 => success
++ 1 => failure */
++int
++setup_d_pid_in_inferior (void)
++{
++ CORE_ADDR anaddr;
++ struct minimal_symbol *msymbol;
++ char buf[4]; /* FIXME 32x64? */
++
++ /* Slam the pid of the process into __d_pid; failing is only a warning! */
++ msymbol = lookup_minimal_symbol ("__d_pid", NULL, symfile_objfile);
++ if (msymbol == NULL)
++ {
++ warning ("Unable to find __d_pid symbol in object file.");
++ warning ("Suggest linking executable with -g (links in /opt/langtools/lib/end.o).");
++ return 1;
++ }
++
++ anaddr = SYMBOL_VALUE_ADDRESS (msymbol);
++ store_unsigned_integer (buf, 4, PIDGET (inferior_ptid)); /* FIXME 32x64? */
++ if (target_write_memory (anaddr, buf, 4)) /* FIXME 32x64? */
++ {
++ warning ("Unable to write __d_pid");
++ warning ("Suggest linking executable with -g (links in /opt/langtools/lib/end.o).");
++ return 1;
++ }
++ return 0;
++}
++
++/* elz: Used to lookup a symbol in the shared libraries.
++ This function calls shl_findsym, indirectly through a
++ call to __d_shl_get. __d_shl_get is in end.c, which is always
++ linked in by the hp compilers/linkers.
++ The call to shl_findsym cannot be made directly because it needs
++ to be active in target address space.
++ inputs: - minimal symbol pointer for the function we want to look up
++ - address in target space of the descriptor for the library
++ where we want to look the symbol up.
++ This address is retrieved using the
++ som_solib_get_solib_by_pc function (somsolib.c).
++ output: - real address in the library of the function.
++ note: the handle can be null, in which case shl_findsym will look for
++ the symbol in all the loaded shared libraries.
++ files to look at if you need reference on this stuff:
++ dld.c, dld_shl_findsym.c
++ end.c
++ man entry for shl_findsym */
++
++CORE_ADDR
++find_stub_with_shl_get (struct minimal_symbol *function, CORE_ADDR handle)
++{
++ struct symbol *get_sym, *symbol2;
++ struct minimal_symbol *buff_minsym, *msymbol;
++ struct type *ftype;
++ struct value **args;
++ struct value *funcval;
++ struct value *val;
++
++ int x, namelen, err_value, tmp = -1;
++ CORE_ADDR endo_buff_addr, value_return_addr, errno_return_addr;
++ CORE_ADDR stub_addr;
++
++
++ args = alloca (sizeof (struct value *) * 8); /* 6 for the arguments and one null one??? */
++ funcval = find_function_in_inferior ("__d_shl_get");
++ get_sym = lookup_symbol ("__d_shl_get", NULL, VAR_DOMAIN, NULL, NULL);
++ buff_minsym = lookup_minimal_symbol ("__buffer", NULL, NULL);
++ msymbol = lookup_minimal_symbol ("__shldp", NULL, NULL);
++ symbol2 = lookup_symbol ("__shldp", NULL, VAR_DOMAIN, NULL, NULL);
++ endo_buff_addr = SYMBOL_VALUE_ADDRESS (buff_minsym);
++ namelen = strlen (DEPRECATED_SYMBOL_NAME (function));
++ value_return_addr = endo_buff_addr + namelen;
++ ftype = check_typedef (SYMBOL_TYPE (get_sym));
++
++ /* do alignment */
++ if ((x = value_return_addr % 64) != 0)
++ value_return_addr = value_return_addr + 64 - x;
++
++ errno_return_addr = value_return_addr + 64;
++
++
++ /* set up stuff needed by __d_shl_get in buffer in end.o */
++
++ target_write_memory (endo_buff_addr, DEPRECATED_SYMBOL_NAME (function), namelen);
++
++ target_write_memory (value_return_addr, (char *) &tmp, 4);
++
++ target_write_memory (errno_return_addr, (char *) &tmp, 4);
++
++ target_write_memory (SYMBOL_VALUE_ADDRESS (msymbol),
++ (char *) &handle, 4);
++
++ /* now prepare the arguments for the call */
++
++ args[0] = value_from_longest (TYPE_FIELD_TYPE (ftype, 0), 12);
++ args[1] = value_from_pointer (TYPE_FIELD_TYPE (ftype, 1), SYMBOL_VALUE_ADDRESS (msymbol));
++ args[2] = value_from_pointer (TYPE_FIELD_TYPE (ftype, 2), endo_buff_addr);
++ args[3] = value_from_longest (TYPE_FIELD_TYPE (ftype, 3), TYPE_PROCEDURE);
++ args[4] = value_from_pointer (TYPE_FIELD_TYPE (ftype, 4), value_return_addr);
++ args[5] = value_from_pointer (TYPE_FIELD_TYPE (ftype, 5), errno_return_addr);
++
++ /* now call the function */
++
++ val = call_function_by_hand (funcval, 6, args);
++
++ /* now get the results */
++
++ target_read_memory (errno_return_addr, (char *) &err_value, sizeof (err_value));
++
++ target_read_memory (value_return_addr, (char *) &stub_addr, sizeof (stub_addr));
++ if (stub_addr <= 0)
++ error ("call to __d_shl_get failed, error code is %d", err_value);
++
++ return (stub_addr);
++}
++
++/* Cover routine for find_stub_with_shl_get to pass to catch_errors */
++static int
++cover_find_stub_with_shl_get (void *args_untyped)
++{
++ args_for_find_stub *args = args_untyped;
++ args->return_val = find_stub_with_shl_get (args->msym, args->solib_handle);
++ return 0;
++}
++
++/* Initialize exception catchpoint support by looking for the
++ necessary hooks/callbacks in end.o, etc., and set the hook value to
++ point to the required debug function
++
++ Return 0 => failure
++ 1 => success */
++
++static int
++initialize_hp_cxx_exception_support (void)
++{
++ struct symtabs_and_lines sals;
++ struct cleanup *old_chain;
++ struct cleanup *canonical_strings_chain = NULL;
++ int i;
++ char *addr_start;
++ char *addr_end = NULL;
++ char **canonical = (char **) NULL;
++ int thread = -1;
++ struct symbol *sym = NULL;
++ struct minimal_symbol *msym = NULL;
++ struct objfile *objfile;
++ asection *shlib_info;
++
++ /* Detect and disallow recursion. On HP-UX with aCC, infinite
++ recursion is a possibility because finding the hook for exception
++ callbacks involves making a call in the inferior, which means
++ re-inserting breakpoints which can re-invoke this code */
++
++ static int recurse = 0;
++ if (recurse > 0)
++ {
++ hp_cxx_exception_support_initialized = 0;
++ exception_support_initialized = 0;
++ return 0;
++ }
++
++ hp_cxx_exception_support = 0;
++
++ /* First check if we have seen any HP compiled objects; if not,
++ it is very unlikely that HP's idiosyncratic callback mechanism
++ for exception handling debug support will be available!
++ This will percolate back up to breakpoint.c, where our callers
++ will decide to try the g++ exception-handling support instead. */
++ if (!hp_som_som_object_present)
++ return 0;
++
++ /* We have a SOM executable with SOM debug info; find the hooks */
++
++ /* First look for the notify hook provided by aCC runtime libs */
++ /* If we find this symbol, we conclude that the executable must
++ have HP aCC exception support built in. If this symbol is not
++ found, even though we're a HP SOM-SOM file, we may have been
++ built with some other compiler (not aCC). This results percolates
++ back up to our callers in breakpoint.c which can decide to
++ try the g++ style of exception support instead.
++ If this symbol is found but the other symbols we require are
++ not found, there is something weird going on, and g++ support
++ should *not* be tried as an alternative.
++
++ ASSUMPTION: Only HP aCC code will have __eh_notify_hook defined.
++ ASSUMPTION: HP aCC and g++ modules cannot be linked together. */
++
++ /* libCsup has this hook; it'll usually be non-debuggable */
++ msym = lookup_minimal_symbol (HP_ACC_EH_notify_hook, NULL, NULL);
++ if (msym)
++ {
++ eh_notify_hook_addr = SYMBOL_VALUE_ADDRESS (msym);
++ hp_cxx_exception_support = 1;
++ }
++ else
++ {
++ warning ("Unable to find exception callback hook (%s).", HP_ACC_EH_notify_hook);
++ warning ("Executable may not have been compiled debuggable with HP aCC.");
++ warning ("GDB will be unable to intercept exception events.");
++ eh_notify_hook_addr = 0;
++ hp_cxx_exception_support = 0;
++ return 0;
++ }
++
++ /* Next look for the notify callback routine in end.o */
++ /* This is always available in the SOM symbol dictionary if end.o is linked in */
++ msym = lookup_minimal_symbol (HP_ACC_EH_notify_callback, NULL, NULL);
++ if (msym)
++ {
++ eh_notify_callback_addr = SYMBOL_VALUE_ADDRESS (msym);
++ hp_cxx_exception_support = 1;
++ }
++ else
++ {
++ warning ("Unable to find exception callback routine (%s).", HP_ACC_EH_notify_callback);
++ warning ("Suggest linking executable with -g (links in /opt/langtools/lib/end.o).");
++ warning ("GDB will be unable to intercept exception events.");
++ eh_notify_callback_addr = 0;
++ return 0;
++ }
++
++#ifndef GDB_TARGET_IS_HPPA_20W
++ /* Check whether the executable is dynamically linked or archive bound */
++ /* With an archive-bound executable we can use the raw addresses we find
++ for the callback function, etc. without modification. For an executable
++ with shared libraries, we have to do more work to find the plabel, which
++ can be the target of a call through $$dyncall from the aCC runtime support
++ library (libCsup) which is linked shared by default by aCC. */
++ /* This test below was copied from somsolib.c/somread.c. It may not be a very
++ reliable one to test that an executable is linked shared. pai/1997-07-18 */
++ shlib_info = bfd_get_section_by_name (symfile_objfile->obfd, "$SHLIB_INFO$");
++ if (shlib_info && (bfd_section_size (symfile_objfile->obfd, shlib_info) != 0))
++ {
++ /* The minsym we have has the local code address, but that's not the
++ plabel that can be used by an inter-load-module call. */
++ /* Find solib handle for main image (which has end.o), and use that
++ and the min sym as arguments to __d_shl_get() (which does the equivalent
++ of shl_findsym()) to find the plabel. */
++
++ args_for_find_stub args;
++ static char message[] = "Error while finding exception callback hook:\n";
++
++ args.solib_handle = som_solib_get_solib_by_pc (eh_notify_callback_addr);
++ args.msym = msym;
++ args.return_val = 0;
++
++ recurse++;
++ catch_errors (cover_find_stub_with_shl_get, &args, message,
++ RETURN_MASK_ALL);
++ eh_notify_callback_addr = args.return_val;
++ recurse--;
++
++ exception_catchpoints_are_fragile = 1;
++
++ if (!eh_notify_callback_addr)
++ {
++ /* We can get here either if there is no plabel in the export list
++ for the main image, or if something strange happened (?) */
++ warning ("Couldn't find a plabel (indirect function label) for the exception callback.");
++ warning ("GDB will not be able to intercept exception events.");
++ return 0;
++ }
++ }
++ else
++ exception_catchpoints_are_fragile = 0;
++#endif
++
++ /* Now, look for the breakpointable routine in end.o */
++ /* This should also be available in the SOM symbol dict. if end.o linked in */
++ msym = lookup_minimal_symbol (HP_ACC_EH_break, NULL, NULL);
++ if (msym)
++ {
++ eh_break_addr = SYMBOL_VALUE_ADDRESS (msym);
++ hp_cxx_exception_support = 1;
++ }
++ else
++ {
++ warning ("Unable to find exception callback routine to set breakpoint (%s).", HP_ACC_EH_break);
++ warning ("Suggest linking executable with -g (link in /opt/langtools/lib/end.o).");
++ warning ("GDB will be unable to intercept exception events.");
++ eh_break_addr = 0;
++ return 0;
++ }
++
++ /* Next look for the catch enable flag provided in end.o */
++ sym = lookup_symbol (HP_ACC_EH_catch_catch, (struct block *) NULL,
++ VAR_DOMAIN, 0, (struct symtab **) NULL);
++ if (sym) /* sometimes present in debug info */
++ {
++ eh_catch_catch_addr = SYMBOL_VALUE_ADDRESS (sym);
++ hp_cxx_exception_support = 1;
++ }
++ else
++ /* otherwise look in SOM symbol dict. */
++ {
++ msym = lookup_minimal_symbol (HP_ACC_EH_catch_catch, NULL, NULL);
++ if (msym)
++ {
++ eh_catch_catch_addr = SYMBOL_VALUE_ADDRESS (msym);
++ hp_cxx_exception_support = 1;
++ }
++ else
++ {
++ warning ("Unable to enable interception of exception catches.");
++ warning ("Executable may not have been compiled debuggable with HP aCC.");
++ warning ("Suggest linking executable with -g (link in /opt/langtools/lib/end.o).");
++ return 0;
++ }
++ }
++
++ /* Next look for the catch enable flag provided end.o */
++ sym = lookup_symbol (HP_ACC_EH_catch_catch, (struct block *) NULL,
++ VAR_DOMAIN, 0, (struct symtab **) NULL);
++ if (sym) /* sometimes present in debug info */
++ {
++ eh_catch_throw_addr = SYMBOL_VALUE_ADDRESS (sym);
++ hp_cxx_exception_support = 1;
++ }
++ else
++ /* otherwise look in SOM symbol dict. */
++ {
++ msym = lookup_minimal_symbol (HP_ACC_EH_catch_throw, NULL, NULL);
++ if (msym)
++ {
++ eh_catch_throw_addr = SYMBOL_VALUE_ADDRESS (msym);
++ hp_cxx_exception_support = 1;
++ }
++ else
++ {
++ warning ("Unable to enable interception of exception throws.");
++ warning ("Executable may not have been compiled debuggable with HP aCC.");
++ warning ("Suggest linking executable with -g (link in /opt/langtools/lib/end.o).");
++ return 0;
++ }
++ }
++
++ /* Set the flags */
++ hp_cxx_exception_support = 2; /* everything worked so far */
++ hp_cxx_exception_support_initialized = 1;
++ exception_support_initialized = 1;
++
++ return 1;
++}
++
++/* Target operation for enabling or disabling interception of
++ exception events.
++ KIND is either EX_EVENT_THROW or EX_EVENT_CATCH
++ ENABLE is either 0 (disable) or 1 (enable).
++ Return value is NULL if no support found;
++ -1 if something went wrong,
++ or a pointer to a symtab/line struct if the breakpointable
++ address was found. */
++
++struct symtab_and_line *
++child_enable_exception_callback (enum exception_event_kind kind, int enable)
++{
++ char buf[4];
++
++ if (!exception_support_initialized || !hp_cxx_exception_support_initialized)
++ if (!initialize_hp_cxx_exception_support ())
++ return NULL;
++
++ switch (hp_cxx_exception_support)
++ {
++ case 0:
++ /* Assuming no HP support at all */
++ return NULL;
++ case 1:
++ /* HP support should be present, but something went wrong */
++ return (struct symtab_and_line *) -1; /* yuck! */
++ /* there may be other cases in the future */
++ }
++
++ /* Set the EH hook to point to the callback routine */
++ store_unsigned_integer (buf, 4, enable ? eh_notify_callback_addr : 0); /* FIXME 32x64 problem */
++ /* pai: (temp) FIXME should there be a pack operation first? */
++ if (target_write_memory (eh_notify_hook_addr, buf, 4)) /* FIXME 32x64 problem */
++ {
++ warning ("Could not write to target memory for exception event callback.");
++ warning ("Interception of exception events may not work.");
++ return (struct symtab_and_line *) -1;
++ }
++ if (enable)
++ {
++ /* Ensure that __d_pid is set up correctly -- end.c code checks this. :-( */
++ if (PIDGET (inferior_ptid) > 0)
++ {
++ if (setup_d_pid_in_inferior ())
++ return (struct symtab_and_line *) -1;
++ }
++ else
++ {
++ warning ("Internal error: Invalid inferior pid? Cannot intercept exception events.");
++ return (struct symtab_and_line *) -1;
++ }
++ }
++
++ switch (kind)
++ {
++ case EX_EVENT_THROW:
++ store_unsigned_integer (buf, 4, enable ? 1 : 0);
++ if (target_write_memory (eh_catch_throw_addr, buf, 4)) /* FIXME 32x64? */
++ {
++ warning ("Couldn't enable exception throw interception.");
++ return (struct symtab_and_line *) -1;
++ }
++ break;
++ case EX_EVENT_CATCH:
++ store_unsigned_integer (buf, 4, enable ? 1 : 0);
++ if (target_write_memory (eh_catch_catch_addr, buf, 4)) /* FIXME 32x64? */
++ {
++ warning ("Couldn't enable exception catch interception.");
++ return (struct symtab_and_line *) -1;
++ }
++ break;
++ default:
++ error ("Request to enable unknown or unsupported exception event.");
++ }
++
++ /* Copy break address into new sal struct, malloc'ing if needed. */
++ if (!break_callback_sal)
++ {
++ break_callback_sal = (struct symtab_and_line *) xmalloc (sizeof (struct symtab_and_line));
++ }
++ init_sal (break_callback_sal);
++ break_callback_sal->symtab = NULL;
++ break_callback_sal->pc = eh_break_addr;
++ break_callback_sal->line = 0;
++ break_callback_sal->end = eh_break_addr;
++
++ return break_callback_sal;
++}
++
++/* Record some information about the current exception event */
++static struct exception_event_record current_ex_event;
++/* Convenience struct */
++static struct symtab_and_line null_symtab_and_line =
++{NULL, 0, 0, 0};
++
++/* Report current exception event. Returns a pointer to a record
++ that describes the kind of the event, where it was thrown from,
++ and where it will be caught. More information may be reported
++ in the future */
++struct exception_event_record *
++child_get_current_exception_event (void)
++{
++ CORE_ADDR event_kind;
++ CORE_ADDR throw_addr;
++ CORE_ADDR catch_addr;
++ struct frame_info *fi, *curr_frame;
++ int level = 1;
++
++ curr_frame = get_current_frame ();
++ if (!curr_frame)
++ return (struct exception_event_record *) NULL;
++
++ /* Go up one frame to __d_eh_notify_callback, because at the
++ point when this code is executed, there's garbage in the
++ arguments of __d_eh_break. */
++ fi = find_relative_frame (curr_frame, &level);
++ if (level != 0)
++ return (struct exception_event_record *) NULL;
++
++ select_frame (fi);
++
++ /* Read in the arguments */
++ /* __d_eh_notify_callback() is called with 3 arguments:
++ 1. event kind catch or throw
++ 2. the target address if known
++ 3. a flag -- not sure what this is. pai/1997-07-17 */
++ event_kind = read_register (ARG0_REGNUM);
++ catch_addr = read_register (ARG1_REGNUM);
++
++ /* Now go down to a user frame */
++ /* For a throw, __d_eh_break is called by
++ __d_eh_notify_callback which is called by
++ __notify_throw which is called
++ from user code.
++ For a catch, __d_eh_break is called by
++ __d_eh_notify_callback which is called by
++ <stackwalking stuff> which is called by
++ __throw__<stuff> or __rethrow_<stuff> which is called
++ from user code. */
++ /* FIXME: Don't use such magic numbers; search for the frames */
++ level = (event_kind == EX_EVENT_THROW) ? 3 : 4;
++ fi = find_relative_frame (curr_frame, &level);
++ if (level != 0)
++ return (struct exception_event_record *) NULL;
++
++ select_frame (fi);
++ throw_addr = get_frame_pc (fi);
++
++ /* Go back to original (top) frame */
++ select_frame (curr_frame);
++
++ current_ex_event.kind = (enum exception_event_kind) event_kind;
++ current_ex_event.throw_sal = find_pc_line (throw_addr, 1);
++ current_ex_event.catch_sal = find_pc_line (catch_addr, 1);
++
++ return &current_ex_event;
++}
++
+ static void
+ hppa_hpux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
+ {
+- set_gdbarch_pc_in_sigtramp (gdbarch, hppa_hpux_pc_in_sigtramp);
++ set_gdbarch_deprecated_pc_in_sigtramp (gdbarch, hppa_hpux_pc_in_sigtramp);
+ }
+
+ static void
+diff -uNr gdb-6.1.orig/gdb/hppa-linux-nat.c gdb-6.1/gdb/hppa-linux-nat.c
+--- gdb-6.1.orig/gdb/hppa-linux-nat.c 1970-01-01 00:00:00.000000000 +0000
++++ gdb-6.1/gdb/hppa-linux-nat.c 2004-05-29 19:37:43.114081288 +0000
+@@ -0,0 +1,350 @@
++/* Functions specific to running gdb native on HPPA running Linux.
++ Copyright 2004 Free Software Foundation, Inc.
++
++ This file is part of GDB.
++
++ This program is free software; you can redistribute it and/or modify
++ it under the terms of the GNU General Public License as published by
++ the Free Software Foundation; either version 2 of the License, or
++ (at your option) any later version.
++
++ This program is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU General Public License for more details.
++
++ You should have received a copy of the GNU General Public License
++ along with this program; if not, write to the Free Software
++ Foundation, Inc., 59 Temple Place - Suite 330,
++ Boston, MA 02111-1307, USA. */
++
++#include "defs.h"
++#include "inferior.h"
++#include "gdbcore.h"
++#include "regcache.h"
++#include "linux-nat.h"
++
++#include "gdb_assert.h"
++#include "gdb_string.h"
++#include <sys/ptrace.h>
++#include <sys/user.h>
++#include <sys/procfs.h>
++#include <string.h>
++
++#ifdef HAVE_SYS_REG_H
++#include <sys/reg.h>
++#endif
++
++#include <asm/offset.h>
++
++/* Prototypes for supply_gregset etc. */
++#include "gregset.h"
++
++#include "hppa-linux-tdep.h"
++
++/* These must match the order of the register names.
++
++ Some sort of lookup table is needed because the offsets associated
++ with the registers are all over the board. */
++
++static const int u_offsets[] =
++ {
++ /* general registers */
++ -1,
++ PT_GR1,
++ PT_GR2,
++ PT_GR3,
++ PT_GR4,
++ PT_GR5,
++ PT_GR6,
++ PT_GR7,
++ PT_GR8,
++ PT_GR9,
++ PT_GR10,
++ PT_GR11,
++ PT_GR12,
++ PT_GR13,
++ PT_GR14,
++ PT_GR15,
++ PT_GR16,
++ PT_GR17,
++ PT_GR18,
++ PT_GR19,
++ PT_GR20,
++ PT_GR21,
++ PT_GR22,
++ PT_GR23,
++ PT_GR24,
++ PT_GR25,
++ PT_GR26,
++ PT_GR27,
++ PT_GR28,
++ PT_GR29,
++ PT_GR30,
++ PT_GR31,
++
++ PT_SAR,
++ PT_IAOQ0,
++ PT_IASQ0,
++ PT_IAOQ1,
++ PT_IASQ1,
++ -1, /* eiem */
++ PT_IIR,
++ PT_ISR,
++ PT_IOR,
++ PT_PSW,
++ -1, /* goto */
++
++ PT_SR4,
++ PT_SR0,
++ PT_SR1,
++ PT_SR2,
++ PT_SR3,
++ PT_SR5,
++ PT_SR6,
++ PT_SR7,
++
++ -1, /* cr0 */
++ -1, /* pid0 */
++ -1, /* pid1 */
++ -1, /* ccr */
++ -1, /* pid2 */
++ -1, /* pid3 */
++ -1, /* cr24 */
++ -1, /* cr25 */
++ -1, /* cr26 */
++ PT_CR27,
++ -1, /* cr28 */
++ -1, /* cr29 */
++ -1, /* cr30 */
++
++ /* Floating point regs. */
++ PT_FR0, PT_FR0 + 4,
++ PT_FR1, PT_FR1 + 4,
++ PT_FR2, PT_FR2 + 4,
++ PT_FR3, PT_FR3 + 4,
++ PT_FR4, PT_FR4 + 4,
++ PT_FR5, PT_FR5 + 4,
++ PT_FR6, PT_FR6 + 4,
++ PT_FR7, PT_FR7 + 4,
++ PT_FR8, PT_FR8 + 4,
++ PT_FR9, PT_FR9 + 4,
++ PT_FR10, PT_FR10 + 4,
++ PT_FR11, PT_FR11 + 4,
++ PT_FR12, PT_FR12 + 4,
++ PT_FR13, PT_FR13 + 4,
++ PT_FR14, PT_FR14 + 4,
++ PT_FR15, PT_FR15 + 4,
++ PT_FR16, PT_FR16 + 4,
++ PT_FR17, PT_FR17 + 4,
++ PT_FR18, PT_FR18 + 4,
++ PT_FR19, PT_FR19 + 4,
++ PT_FR20, PT_FR20 + 4,
++ PT_FR21, PT_FR21 + 4,
++ PT_FR22, PT_FR22 + 4,
++ PT_FR23, PT_FR23 + 4,
++ PT_FR24, PT_FR24 + 4,
++ PT_FR25, PT_FR25 + 4,
++ PT_FR26, PT_FR26 + 4,
++ PT_FR27, PT_FR27 + 4,
++ PT_FR28, PT_FR28 + 4,
++ PT_FR29, PT_FR29 + 4,
++ PT_FR30, PT_FR30 + 4,
++ PT_FR31, PT_FR31 + 4,
++ };
++
++CORE_ADDR
++register_addr (int regno, CORE_ADDR blockend)
++{
++ CORE_ADDR addr;
++
++ if ((unsigned) regno >= NUM_REGS)
++ error ("Invalid register number %d.", regno);
++
++ if (u_offsets[regno] == -1)
++ addr = 0;
++ else
++ {
++ addr = (CORE_ADDR) u_offsets[regno];
++ }
++
++ return addr;
++}
++
++int pa_cannot_fetch_register (regno)
++ int regno;
++{
++ return (unsigned int) regno >= NUM_REGS || u_offsets[regno] == -1;
++}
++
++int pa_cannot_store_register (regno)
++ int regno;
++{
++ return ((unsigned int) regno >= NUM_REGS
++ || regno == PA_GR0_REGNUM
++ || regno == PA_PCSQ_HEAD_REGNUM
++ || (regno >= PA_PCSQ_TAIL_REGNUM && regno < PA_IPSW_REGNUM)
++ || (regno > PA_IPSW_REGNUM && regno < PA_FR4_REGNUM));
++}
++
++static const int greg_map[] =
++ {
++ PA_GR0_REGNUM,
++ PA_GR1_REGNUM,
++ PA_GR2_REGNUM,
++ PA_GR3_REGNUM,
++ PA_GR4_REGNUM,
++ PA_GR5_REGNUM,
++ PA_GR6_REGNUM,
++ PA_GR7_REGNUM,
++ PA_GR8_REGNUM,
++ PA_GR9_REGNUM,
++ PA_GR10_REGNUM,
++ PA_GR11_REGNUM,
++ PA_GR12_REGNUM,
++ PA_GR13_REGNUM,
++ PA_GR14_REGNUM,
++ PA_GR15_REGNUM,
++ PA_GR16_REGNUM,
++ PA_GR17_REGNUM,
++ PA_GR18_REGNUM,
++ PA_GR19_REGNUM,
++ PA_GR20_REGNUM,
++ PA_GR21_REGNUM,
++ PA_GR22_REGNUM,
++ PA_GR23_REGNUM,
++ PA_GR24_REGNUM,
++ PA_GR25_REGNUM,
++ PA_GR26_REGNUM,
++ PA_GR27_REGNUM,
++ PA_GR28_REGNUM,
++ PA_GR29_REGNUM,
++ PA_GR30_REGNUM,
++ PA_GR31_REGNUM,
++ PA_SR0_REGNUM,
++ PA_SR1_REGNUM,
++ PA_SR2_REGNUM,
++ PA_SR3_REGNUM,
++ PA_SR4_REGNUM,
++ PA_SR5_REGNUM,
++ PA_SR6_REGNUM,
++ PA_SR7_REGNUM,
++ PA_PCOQ_HEAD_REGNUM,
++ PA_PCOQ_TAIL_REGNUM,
++ PA_PCSQ_HEAD_REGNUM,
++ PA_PCSQ_TAIL_REGNUM,
++ PA_CR11_REGNUM,
++ PA_CR19_REGNUM,
++ PA_CR20_REGNUM,
++ PA_CR21_REGNUM,
++ PA_CR22_REGNUM,
++ PA_CR0_REGNUM,
++ PA_CR24_REGNUM,
++ PA_CR25_REGNUM,
++ PA_CR26_REGNUM,
++ PA_CR27_REGNUM,
++ PA_CR28_REGNUM,
++ PA_CR29_REGNUM,
++ PA_CR30_REGNUM,
++ PA_CR31_REGNUM,
++ PA_CR8_REGNUM,
++ PA_CR9_REGNUM,
++ PA_CR12_REGNUM,
++ PA_CR13_REGNUM,
++ PA_CR10_REGNUM,
++ PA_CR15_REGNUM
++ };
++
++void
++supply_gregset (gdb_gregset_t *gregsetp)
++{
++ int i;
++ greg_t *regp = (greg_t *) gregsetp;
++
++ for (i = 0; i < sizeof (greg_map) / sizeof (greg_map[0]); i++, regp++)
++ {
++ int regno = greg_map[i];
++ /* When running a 64 bit kernel, a greg_t may be larger than the
++ actual register, so just pick off the LS bits of big-endian word. */
++ supply_register (regno,
++ ((char *) (regp + 1)) - register_size (current_gdbarch, regno));
++ }
++}
++
++void
++fill_gregset (gdb_gregset_t *gregsetp, int regno)
++{
++ int i;
++ greg_t *regp = (greg_t *) gregsetp;
++
++ memset (gregsetp, 0, sizeof (*gregsetp));
++ for (i = 0; i < sizeof (greg_map) / sizeof (greg_map[0]); i++, regp++)
++ {
++ int regi = greg_map[i];
++
++ if (regno == -1 || regi == regno)
++ {
++ int rawsize = register_size (current_gdbarch, regi);
++ regcache_collect (regi, ((char *) (regp + 1)) - rawsize);
++ }
++ }
++}
++
++/* Given a pointer to a floating point register set in /proc format
++ (fpregset_t *), unpack the register contents and supply them as gdb's
++ idea of the current floating point register values. */
++
++void
++supply_fpregset (gdb_fpregset_t *fpregsetp)
++{
++ register int regi;
++ char *from;
++
++ for (regi = 0; regi <= 31; regi++)
++ {
++ from = (char *) &((*fpregsetp)[regi]);
++ supply_register (2*regi + PA_FR0_REGNUM, from);
++ supply_register (2*regi + PA_FR0_REGNUM + 1, from + 4);
++ }
++}
++
++/* Given a pointer to a floating point register set in /proc format
++ (fpregset_t *), update the register specified by REGNO from gdb's idea
++ of the current floating point register set. If REGNO is -1, update
++ them all. */
++
++void
++fill_fpregset (gdb_fpregset_t *fpregsetp, int regno)
++{
++ if (regno == -1)
++ deprecated_read_register_bytes (DEPRECATED_REGISTER_BYTE (PA_FR0_REGNUM),
++ (char *)fpregsetp,
++ 32 * 2 * DEPRECATED_REGISTER_RAW_SIZE (PA_FR0_REGNUM));
++ else
++ {
++ /* Gross. fpregset_t is double, registers[x] has single
++ precision reg. */
++ char *to = (char *) &((*fpregsetp)[(regno - PA_FR0_REGNUM) / 2]);
++ if ((regno - PA_FR0_REGNUM) & 1)
++ to += 4;
++ regcache_collect (regno, to);
++ }
++}
++
++int
++pa_linux_insert_watchpoint (int pid, CORE_ADDR addr, int len, int rw)
++{
++ return -1;
++}
++
++int
++pa_linux_remove_watchpoint (int pid, CORE_ADDR addr, int len)
++{
++ return -1;
++}
++
++CORE_ADDR
++pa_linux_stopped_by_watchpoint (int pid)
++{
++ return 0;
++}
+diff -uNr gdb-6.1.orig/gdb/hppa-linux-tdep.c gdb-6.1/gdb/hppa-linux-tdep.c
+--- gdb-6.1.orig/gdb/hppa-linux-tdep.c 1970-01-01 00:00:00.000000000 +0000
++++ gdb-6.1/gdb/hppa-linux-tdep.c 2004-05-29 19:37:43.117080832 +0000
+@@ -0,0 +1,58 @@
++/* Target-dependent code for Linux running on PA-RISC, for GDB.
++
++ Copyright 2004 Free Software Foundation, Inc.
++
++This file is part of GDB.
++
++This program is free software; you can redistribute it and/or modify
++it under the terms of the GNU General Public License as published by
++the Free Software Foundation; either version 2 of the License, or
++(at your option) any later version.
++
++This program is distributed in the hope that it will be useful,
++but WITHOUT ANY WARRANTY; without even the implied warranty of
++MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++GNU General Public License for more details.
++
++You should have received a copy of the GNU General Public License
++along with this program; if not, write to the Free Software
++Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
++
++#include "defs.h"
++#include "arch-utils.h"
++#include "gdbcore.h"
++#include "osabi.h"
++#include "gdb_string.h"
++#include "frame.h"
++#include "inferior.h"
++#include "target.h"
++#include "objfiles.h"
++#include "elf/common.h"
++#include "solib-svr4.h"
++#include "glibc-tdep.h"
++
++#include "hppa-linux-tdep.h"
++
++/* Forward declarations. */
++extern initialize_file_ftype _initialize_hppa_linux_tdep;
++
++static void
++hppa_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
++{
++ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
++
++ /* GNU/Linux uses SVR4-style shared libraries. */
++ set_solib_svr4_fetch_link_map_offsets
++ (gdbarch, svr4_ilp32_fetch_link_map_offsets);
++
++ /* GNU/Linux uses the dynamic linker included in the GNU C Library. */
++ set_gdbarch_skip_solib_resolver (gdbarch, glibc_skip_solib_resolver);
++}
++
++void
++_initialize_hppa_linux_tdep (void)
++{
++ gdbarch_register_osabi (bfd_arch_hppa, 0, GDB_OSABI_LINUX, hppa_linux_init_abi);
++}
++
++
+diff -uNr gdb-6.1.orig/gdb/hppa-linux-tdep.h gdb-6.1/gdb/hppa-linux-tdep.h
+--- gdb-6.1.orig/gdb/hppa-linux-tdep.h 1970-01-01 00:00:00.000000000 +0000
++++ gdb-6.1/gdb/hppa-linux-tdep.h 2004-05-29 19:37:43.121080224 +0000
+@@ -0,0 +1,140 @@
++/* Definitions to target GDB to any Hewlett-Packard PA-RISC machine.
++ Copyright 2004 Free Software Foundation, Inc.
++
++ Contributed by Randolph Chung <tausq@debian.org>
++
++ This file is part of GDB.
++
++ This program is free software; you can redistribute it and/or modify
++ it under the terms of the GNU General Public License as published by
++ the Free Software Foundation; either version 2 of the License, or
++ (at your option) any later version.
++
++ This program is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU General Public License for more details.
++
++ You should have received a copy of the GNU General Public License
++ along with this program; if not, write to the Free Software
++ Foundation, Inc., 59 Temple Place - Suite 330,
++ Boston, MA 02111-1307, USA. */
++
++#ifndef HPPA_LINUX_TDEP_H
++#define HPPA_LINUX_TDEP_H
++
++#include "hppa-tdep.h"
++
++/* Register numbers of various registers, */
++
++/* General registers. */
++#define PA_GR0_REGNUM 0
++#define PA_GR1_REGNUM (PA_GR0_REGNUM+1)
++#define PA_GR2_REGNUM (PA_GR0_REGNUM+2)
++#define PA_GR3_REGNUM (PA_GR0_REGNUM+3)
++#define PA_GR4_REGNUM (PA_GR0_REGNUM+4)
++#define PA_GR5_REGNUM (PA_GR0_REGNUM+5)
++#define PA_GR6_REGNUM (PA_GR0_REGNUM+6)
++#define PA_GR7_REGNUM (PA_GR0_REGNUM+7)
++#define PA_GR8_REGNUM (PA_GR0_REGNUM+8)
++#define PA_GR9_REGNUM (PA_GR0_REGNUM+9)
++#define PA_GR10_REGNUM (PA_GR0_REGNUM+10)
++#define PA_GR11_REGNUM (PA_GR0_REGNUM+11)
++#define PA_GR12_REGNUM (PA_GR0_REGNUM+12)
++#define PA_GR13_REGNUM (PA_GR0_REGNUM+13)
++#define PA_GR14_REGNUM (PA_GR0_REGNUM+14)
++#define PA_GR15_REGNUM (PA_GR0_REGNUM+15)
++#define PA_GR16_REGNUM (PA_GR0_REGNUM+16)
++#define PA_GR17_REGNUM (PA_GR0_REGNUM+17)
++#define PA_GR18_REGNUM (PA_GR0_REGNUM+18)
++#define PA_GR19_REGNUM (PA_GR0_REGNUM+19)
++#define PA_GR20_REGNUM (PA_GR0_REGNUM+20)
++#define PA_GR21_REGNUM (PA_GR0_REGNUM+21)
++#define PA_GR22_REGNUM (PA_GR0_REGNUM+22)
++#define PA_GR23_REGNUM (PA_GR0_REGNUM+23)
++#define PA_GR24_REGNUM (PA_GR0_REGNUM+24)
++#define PA_GR25_REGNUM (PA_GR0_REGNUM+25)
++#define PA_GR26_REGNUM (PA_GR0_REGNUM+26)
++#define PA_GR27_REGNUM (PA_GR0_REGNUM+27)
++#define PA_GR28_REGNUM (PA_GR0_REGNUM+28)
++#define PA_GR29_REGNUM (PA_GR0_REGNUM+29)
++#define PA_GR30_REGNUM (PA_GR0_REGNUM+30)
++#define PA_GR31_REGNUM (PA_GR0_REGNUM+31)
++
++/* Control registers. The peculiar layout is to match HPUX interrupt save
++ state. */
++#define PA_CR11_REGNUM 32
++#define PA_PCOQ_HEAD_REGNUM 33 /* CR18 */
++#define PA_PCSQ_HEAD_REGNUM 34 /* CR17 */
++#define PA_PCOQ_TAIL_REGNUM 35 /* CR18 */
++#define PA_PCSQ_TAIL_REGNUM 36 /* CR17 */
++#define PA_CR15_REGNUM 37
++#define PA_CR19_REGNUM 38
++#define PA_CR20_REGNUM 39
++#define PA_CR21_REGNUM 40
++#define PA_CR22_REGNUM 41
++#define PA_CR31_REGNUM 42
++
++/* Space registers. */
++#define PA_SR4_REGNUM 43
++#define PA_SR0_REGNUM 44
++#define PA_SR1_REGNUM 45
++#define PA_SR2_REGNUM 46
++#define PA_SR3_REGNUM 47
++#define PA_SR5_REGNUM 48
++#define PA_SR6_REGNUM 49
++#define PA_SR7_REGNUM 50
++
++/* More control regs. */
++#define PA_CR0_REGNUM 51
++#define PA_CR8_REGNUM 52
++#define PA_CR9_REGNUM 53
++#define PA_CR10_REGNUM 54
++#define PA_CR12_REGNUM 55
++#define PA_CR13_REGNUM 56
++#define PA_CR24_REGNUM 57
++#define PA_CR25_REGNUM 58
++#define PA_CR26_REGNUM 59
++#define PA_CR27_REGNUM 60
++#define PA_CR28_REGNUM 61
++#define PA_CR29_REGNUM 62
++#define PA_CR30_REGNUM 63
++
++/* Floating point registers. */
++#define PA_FR0_REGNUM 64
++#define PA_FR1_REGNUM (PA_FR0_REGNUM+2)
++#define PA_FR2_REGNUM (PA_FR0_REGNUM+4)
++#define PA_FR3_REGNUM (PA_FR0_REGNUM+6)
++#define PA_FR4_REGNUM (PA_FR0_REGNUM+8)
++#define PA_FR5_REGNUM (PA_FR0_REGNUM+10)
++#define PA_FR6_REGNUM (PA_FR0_REGNUM+12)
++#define PA_FR7_REGNUM (PA_FR0_REGNUM+14)
++#define PA_FR31_REGNUM (PA_FR0_REGNUM+62)
++
++/* Some aliases. */
++#define PA_FLAGS_REGNUM PA_GR0_REGNUM
++#define PA_SAR_REGNUM PA_CR11_REGNUM
++#define PA_IPSW_REGNUM PA_CR22_REGNUM
++
++/*
++ * Processor Status Word Masks
++ */
++
++#define PSW_T 0x01000000 /* Taken Branch Trap Enable */
++#define PSW_H 0x00800000 /* Higher-Privilege Transfer Trap Enable */
++#define PSW_L 0x00400000 /* Lower-Privilege Transfer Trap Enable */
++#define PSW_N 0x00200000 /* PC Queue Front Instruction Nullified */
++#define PSW_X 0x00100000 /* Data Memory Break Disable */
++#define PSW_B 0x00080000 /* Taken Branch in Previous Cycle */
++#define PSW_C 0x00040000 /* Code Address Translation Enable */
++#define PSW_V 0x00020000 /* Divide Step Correction */
++#define PSW_M 0x00010000 /* High-Priority Machine Check Disable */
++#define PSW_CB 0x0000ff00 /* Carry/Borrow Bits */
++#define PSW_R 0x00000010 /* Recovery Counter Enable */
++#define PSW_Q 0x00000008 /* Interruption State Collection Enable */
++#define PSW_P 0x00000004 /* Protection ID Validation Enable */
++#define PSW_D 0x00000002 /* Data Address Translation Enable */
++#define PSW_I 0x00000001 /* External, Power Failure, Low-Priority */
++ /* Machine Check Interruption Enable */
++#endif
++
+diff -uNr gdb-6.1.orig/gdb/hppa-tdep.c gdb-6.1/gdb/hppa-tdep.c
+--- gdb-6.1.orig/gdb/hppa-tdep.c 2004-05-29 19:34:05.471168040 +0000
++++ gdb-6.1/gdb/hppa-tdep.c 2004-05-29 19:49:00.114161632 +0000
+@@ -48,12 +48,10 @@
+ #include <sys/types.h>
+ #endif
+
+-#include <dl.h>
+ #include <sys/param.h>
+ #include <signal.h>
+
+ #include <sys/ptrace.h>
+-#include <machine/save_state.h>
+
+ #ifdef COFF_ENCAPSULATE
+ #include "a.out.encap.h"
+@@ -76,26 +74,12 @@
+ static const int hppa32_num_regs = 128;
+ static const int hppa64_num_regs = 96;
+
+-static const int hppa64_call_dummy_breakpoint_offset = 22 * 4;
+-
+-/* DEPRECATED_CALL_DUMMY_LENGTH is computed based on the size of a
+- word on the target machine, not the size of an instruction. Since
+- a word on this target holds two instructions we have to divide the
+- instruction size by two to get the word size of the dummy. */
+-static const int hppa32_call_dummy_length = INSTRUCTION_SIZE * 28;
+-static const int hppa64_call_dummy_length = INSTRUCTION_SIZE * 26 / 2;
+-
+ /* Get at various relevent fields of an instruction word. */
+ #define MASK_5 0x1f
+ #define MASK_11 0x7ff
+ #define MASK_14 0x3fff
+ #define MASK_21 0x1fffff
+
+-/* Define offsets into the call dummy for the target function address.
+- See comments related to CALL_DUMMY for more info. */
+-#define FUNC_LDIL_OFFSET (INSTRUCTION_SIZE * 9)
+-#define FUNC_LDO_OFFSET (INSTRUCTION_SIZE * 10)
+-
+ /* Define offsets into the call dummy for the _sr4export address.
+ See comments related to CALL_DUMMY for more info. */
+ #define SR4EXPORT_LDIL_OFFSET (INSTRUCTION_SIZE * 12)
+@@ -118,24 +102,12 @@
+
+ static unsigned extract_5r_store (unsigned int);
+
+-static void hppa_frame_init_saved_regs (struct frame_info *frame);
+-
+-static void find_dummy_frame_regs (struct frame_info *, CORE_ADDR *);
+-
+-static int find_proc_framesize (CORE_ADDR);
+-
+-static int find_return_regnum (CORE_ADDR);
+-
+ struct unwind_table_entry *find_unwind_entry (CORE_ADDR);
+
+ static int extract_17 (unsigned int);
+
+-static unsigned deposit_21 (unsigned int, unsigned int);
+-
+ static int extract_21 (unsigned);
+
+-static unsigned deposit_14 (int, unsigned int);
+-
+ static int extract_14 (unsigned);
+
+ static void unwind_command (char *, int);
+@@ -144,8 +116,6 @@
+
+ static int sign_extend (unsigned int, unsigned int);
+
+-static int restore_pc_queue (CORE_ADDR *);
+-
+ static int hppa_alignof (struct type *);
+
+ static int prologue_inst_adjust_sp (unsigned long);
+@@ -156,10 +126,6 @@
+
+ static int inst_saves_fr (unsigned long);
+
+-static int pc_in_interrupt_handler (CORE_ADDR);
+-
+-static int pc_in_linker_stub (CORE_ADDR);
+-
+ static int compare_unwind_entries (const void *, const void *);
+
+ static void read_unwind_info (struct objfile *);
+@@ -168,11 +134,6 @@
+ struct unwind_table_entry *,
+ asection *, unsigned int,
+ unsigned int, CORE_ADDR);
+-static void pa_print_registers (char *, int, int);
+-static void pa_strcat_registers (char *, int, int, struct ui_file *);
+-static void pa_register_look_aside (char *, int, long *);
+-static void pa_print_fp_reg (int);
+-static void pa_strcat_fp_reg (int, struct ui_file *, enum precision_type);
+ static void record_text_segment_lowaddr (bfd *, asection *, void *);
+ /* FIXME: brobecker 2002-11-07: We will likely be able to make the
+ following functions static, once we hppa is partially multiarched. */
+@@ -181,67 +142,16 @@
+ CORE_ADDR hppa_skip_trampoline_code (CORE_ADDR pc);
+ int hppa_in_solib_call_trampoline (CORE_ADDR pc, char *name);
+ int hppa_in_solib_return_trampoline (CORE_ADDR pc, char *name);
+-CORE_ADDR hppa_saved_pc_after_call (struct frame_info *frame);
+ int hppa_inner_than (CORE_ADDR lhs, CORE_ADDR rhs);
+-CORE_ADDR hppa64_stack_align (CORE_ADDR sp);
+ int hppa_pc_requires_run_before_use (CORE_ADDR pc);
+ int hppa_instruction_nullified (void);
+-int hppa_register_raw_size (int reg_nr);
+-int hppa_register_byte (int reg_nr);
+-struct type * hppa32_register_virtual_type (int reg_nr);
+-struct type * hppa64_register_virtual_type (int reg_nr);
+-void hppa_store_struct_return (CORE_ADDR addr, CORE_ADDR sp);
+-void hppa64_extract_return_value (struct type *type, char *regbuf,
+- char *valbuf);
+-int hppa64_use_struct_convention (int gcc_p, struct type *type);
+-void hppa64_store_return_value (struct type *type, char *valbuf);
+ int hppa_cannot_store_register (int regnum);
+-void hppa_init_extra_frame_info (int fromleaf, struct frame_info *frame);
+-CORE_ADDR hppa_frame_chain (struct frame_info *frame);
+-int hppa_frame_chain_valid (CORE_ADDR chain, struct frame_info *thisframe);
+-int hppa_frameless_function_invocation (struct frame_info *frame);
+-CORE_ADDR hppa_frame_saved_pc (struct frame_info *frame);
+-CORE_ADDR hppa_frame_args_address (struct frame_info *fi);
+-int hppa_frame_num_args (struct frame_info *frame);
+-void hppa_push_dummy_frame (void);
+-void hppa_pop_frame (void);
+-CORE_ADDR hppa_fix_call_dummy (char *dummy, CORE_ADDR pc, CORE_ADDR fun,
+- int nargs, struct value **args,
+- struct type *type, int gcc_p);
+-CORE_ADDR hppa_push_arguments (int nargs, struct value **args, CORE_ADDR sp,
+- int struct_return, CORE_ADDR struct_addr);
+ CORE_ADDR hppa_smash_text_address (CORE_ADDR addr);
+ CORE_ADDR hppa_target_read_pc (ptid_t ptid);
+ void hppa_target_write_pc (CORE_ADDR v, ptid_t ptid);
+-CORE_ADDR hppa_target_read_fp (void);
+-
+-typedef struct
+- {
+- struct minimal_symbol *msym;
+- CORE_ADDR solib_handle;
+- CORE_ADDR return_val;
+- }
+-args_for_find_stub;
+-
+-static int cover_find_stub_with_shl_get (void *);
+
+ static int is_pa_2 = 0; /* False */
+
+-/* This is declared in symtab.c; set to 1 in hp-symtab-read.c */
+-extern int hp_som_som_object_present;
+-
+-/* In breakpoint.c */
+-extern int exception_catchpoints_are_fragile;
+-
+-/* Should call_function allocate stack space for a struct return? */
+-
+-int
+-hppa64_use_struct_convention (int gcc_p, struct type *type)
+-{
+- /* RM: struct upto 128 bits are returned in registers */
+- return TYPE_LENGTH (type) > 16;
+-}
+-
+ /* Handle 32/64-bit struct return conventions. */
+
+ static enum return_value_convention
+@@ -303,7 +213,8 @@
+ are in r28, padded on the left. Aggregates less that 65 bits are
+ in r28, right padded. Aggregates upto 128 bits are in r28 and
+ r29, right padded. */
+- if (TYPE_CODE (type) == TYPE_CODE_FLT)
++ if (TYPE_CODE (type) == TYPE_CODE_FLT
++ && TYPE_LENGTH (type) <= 8)
+ {
+ /* Floats are right aligned? */
+ int offset = register_size (gdbarch, FP4_REGNUM) - TYPE_LENGTH (type);
+@@ -333,15 +244,15 @@
+ int b;
+ for (b = 0; b < TYPE_LENGTH (type); b += 8)
+ {
+- int part = (TYPE_LENGTH (type) - b - 1) % 8 + 1;
++ int part = min (8, TYPE_LENGTH (type) - b);
+ if (readbuf != NULL)
+- regcache_cooked_read_part (regcache, 28, 0, part,
++ regcache_cooked_read_part (regcache, 28 + b / 8, 0, part,
+ (char *) readbuf + b);
+ if (writebuf != NULL)
+- regcache_cooked_write_part (regcache, 28, 0, part,
++ regcache_cooked_write_part (regcache, 28 + b / 8, 0, part,
+ (const char *) writebuf + b);
+ }
+- return RETURN_VALUE_REGISTER_CONVENTION;
++ return RETURN_VALUE_REGISTER_CONVENTION;
+ }
+ else
+ return RETURN_VALUE_STRUCT_CONVENTION;
+@@ -408,16 +319,6 @@
+ return low_sign_extend (word & MASK_14, 14);
+ }
+
+-/* deposit a 14 bit constant in a word */
+-
+-static unsigned
+-deposit_14 (int opnd, unsigned word)
+-{
+- unsigned sign = (opnd < 0 ? 1 : 0);
+-
+- return word | ((unsigned) opnd << 1 & MASK_14) | sign;
+-}
+-
+ /* extract a 21 bit constant */
+
+ static int
+@@ -439,27 +340,6 @@
+ return sign_extend (val, 21) << 11;
+ }
+
+-/* deposit a 21 bit constant in a word. Although 21 bit constants are
+- usually the top 21 bits of a 32 bit constant, we assume that only
+- the low 21 bits of opnd are relevant */
+-
+-static unsigned
+-deposit_21 (unsigned opnd, unsigned word)
+-{
+- unsigned val = 0;
+-
+- val |= get_field (opnd, 11 + 14, 11 + 18);
+- val <<= 2;
+- val |= get_field (opnd, 11 + 12, 11 + 13);
+- val <<= 2;
+- val |= get_field (opnd, 11 + 19, 11 + 20);
+- val <<= 11;
+- val |= get_field (opnd, 11 + 1, 11 + 11);
+- val <<= 1;
+- val |= get_field (opnd, 11 + 0, 11 + 0);
+- return word | val;
+-}
+-
+ /* extract a 17 bit constant from branch instructions, returning the
+ 19 bit signed value. */
+
+@@ -902,2496 +782,334 @@
+ return u->Total_frame_size << 3;
+ }
+
+-/* Called to determine if PC is in an interrupt handler of some
+- kind. */
+-
+-static int
+-pc_in_interrupt_handler (CORE_ADDR pc)
+-{
+- struct unwind_table_entry *u;
+- struct minimal_symbol *msym_us;
+-
+- u = find_unwind_entry (pc);
+- if (!u)
+- return 0;
+-
+- /* Oh joys. HPUX sets the interrupt bit for _sigreturn even though
+- its frame isn't a pure interrupt frame. Deal with this. */
+- msym_us = lookup_minimal_symbol_by_pc (pc);
+-
+- return (u->HP_UX_interrupt_marker
+- && !PC_IN_SIGTRAMP (pc, DEPRECATED_SYMBOL_NAME (msym_us)));
+-}
+-
+-/* Called when no unwind descriptor was found for PC. Returns 1 if it
+- appears that PC is in a linker stub.
++/* This function pushes a stack frame with arguments as part of the
++ inferior function calling mechanism.
+
+- ?!? Need to handle stubs which appear in PA64 code. */
++ This is the version of the function for the 32-bit PA machines, in
++ which later arguments appear at lower addresses. (The stack always
++ grows towards higher addresses.)
+
+-static int
+-pc_in_linker_stub (CORE_ADDR pc)
++ We simply allocate the appropriate amount of stack space and put
++ arguments into their proper slots. */
++
++CORE_ADDR
++hppa32_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
++ struct regcache *regcache, CORE_ADDR bp_addr,
++ int nargs, struct value **args, CORE_ADDR sp,
++ int struct_return, CORE_ADDR struct_addr)
+ {
+- int found_magic_instruction = 0;
+- int i;
+- char buf[4];
++ /* NOTE: cagney/2004-02-27: This is a guess - its implemented by
++ reverse engineering testsuite failures. */
+
+- /* If unable to read memory, assume pc is not in a linker stub. */
+- if (target_read_memory (pc, buf, 4) != 0)
+- return 0;
++ /* Stack base address at which any pass-by-reference parameters are
++ stored. */
++ CORE_ADDR struct_end = 0;
++ /* Stack base address at which the first parameter is stored. */
++ CORE_ADDR param_end = 0;
+
+- /* We are looking for something like
++ /* The inner most end of the stack after all the parameters have
++ been pushed. */
++ CORE_ADDR new_sp = 0;
+
+- ; $$dyncall jams RP into this special spot in the frame (RP')
+- ; before calling the "call stub"
+- ldw -18(sp),rp
+-
+- ldsid (rp),r1 ; Get space associated with RP into r1
+- mtsp r1,sp ; Move it into space register 0
+- be,n 0(sr0),rp) ; back to your regularly scheduled program */
+-
+- /* Maximum known linker stub size is 4 instructions. Search forward
+- from the given PC, then backward. */
+- for (i = 0; i < 4; i++)
++ /* Two passes. First pass computes the location of everything,
++ second pass writes the bytes out. */
++ int write_pass;
++ for (write_pass = 0; write_pass < 2; write_pass++)
+ {
+- /* If we hit something with an unwind, stop searching this direction. */
+-
+- if (find_unwind_entry (pc + i * 4) != 0)
+- break;
++ CORE_ADDR struct_ptr = 0;
++ CORE_ADDR param_ptr = 0;
++ int reg = 27; /* NOTE: Registers go down. */
++ int i;
++ for (i = 0; i < nargs; i++)
++ {
++ struct value *arg = args[i];
++ struct type *type = check_typedef (VALUE_TYPE (arg));
++ /* The corresponding parameter that is pushed onto the
++ stack, and [possibly] passed in a register. */
++ char param_val[8];
++ int param_len;
++ memset (param_val, 0, sizeof param_val);
++ if (TYPE_LENGTH (type) > 8)
++ {
++ /* Large parameter, pass by reference. Store the value
++ in "struct" area and then pass its address. */
++ param_len = 4;
++ struct_ptr += align_up (TYPE_LENGTH (type), 8);
++ if (write_pass)
++ write_memory (struct_end - struct_ptr, VALUE_CONTENTS (arg),
++ TYPE_LENGTH (type));
++ store_unsigned_integer (param_val, 4, struct_end - struct_ptr);
++ }
++ else if (TYPE_CODE (type) == TYPE_CODE_INT
++ || TYPE_CODE (type) == TYPE_CODE_ENUM)
++ {
++ /* Integer value store, right aligned. "unpack_long"
++ takes care of any sign-extension problems. */
++ param_len = align_up (TYPE_LENGTH (type), 4);
++ store_unsigned_integer (param_val, param_len,
++ unpack_long (type,
++ VALUE_CONTENTS (arg)));
++ }
++ else
++ {
++ /* Small struct value, store right aligned? */
++ param_len = align_up (TYPE_LENGTH (type), 4);
++ memcpy (param_val + param_len - TYPE_LENGTH (type),
++ VALUE_CONTENTS (arg), TYPE_LENGTH (type));
++ }
++ param_ptr += param_len;
++ reg -= param_len / 4;
++ if (write_pass)
++ {
++ write_memory (param_end - param_ptr, param_val, param_len);
++ if (reg >= 23)
++ {
++ regcache_cooked_write (regcache, reg, param_val);
++ if (param_len > 4)
++ regcache_cooked_write (regcache, reg + 1, param_val + 4);
++ }
++ }
++ }
+
+- /* Check for ldsid (rp),r1 which is the magic instruction for a
+- return from a cross-space function call. */
+- if (read_memory_integer (pc + i * 4, 4) == 0x004010a1)
++ /* Update the various stack pointers. */
++ if (!write_pass)
+ {
+- found_magic_instruction = 1;
+- break;
++ struct_end = sp + struct_ptr;
++ /* PARAM_PTR already accounts for all the arguments passed
++ by the user. However, the ABI mandates minimum stack
++ space allocations for outgoing arguments. The ABI also
++ mandates minimum stack alignments which we must
++ preserve. */
++ param_end = struct_end + max (align_up (param_ptr, 8), 16);
+ }
+- /* Add code to handle long call/branch and argument relocation stubs
+- here. */
+ }
+
+- if (found_magic_instruction != 0)
+- return 1;
++ /* If a structure has to be returned, set up register 28 to hold its
++ address */
++ if (struct_return)
++ write_register (28, struct_addr);
+
+- /* Now look backward. */
+- for (i = 0; i < 4; i++)
+- {
+- /* If we hit something with an unwind, stop searching this direction. */
++ /* Set the return address. */
++ regcache_cooked_write_unsigned (regcache, RP_REGNUM, bp_addr);
+
+- if (find_unwind_entry (pc - i * 4) != 0)
+- break;
++ /* Update the Stack Pointer. */
++ regcache_cooked_write_unsigned (regcache, SP_REGNUM, param_end + 32);
+
+- /* Check for ldsid (rp),r1 which is the magic instruction for a
+- return from a cross-space function call. */
+- if (read_memory_integer (pc - i * 4, 4) == 0x004010a1)
+- {
+- found_magic_instruction = 1;
+- break;
+- }
+- /* Add code to handle long call/branch and argument relocation stubs
+- here. */
+- }
+- return found_magic_instruction;
++ /* The stack will have 32 bytes of additional space for a frame marker. */
++ return param_end + 32;
+ }
+
+-static int
+-find_return_regnum (CORE_ADDR pc)
+-{
+- struct unwind_table_entry *u;
+-
+- u = find_unwind_entry (pc);
+-
+- if (!u)
+- return RP_REGNUM;
++/* This function pushes a stack frame with arguments as part of the
++ inferior function calling mechanism.
+
+- if (u->Millicode)
+- return 31;
++ This is the version for the PA64, in which later arguments appear
++ at higher addresses. (The stack always grows towards higher
++ addresses.)
+
+- return RP_REGNUM;
+-}
++ We simply allocate the appropriate amount of stack space and put
++ arguments into their proper slots.
+
+-/* Return size of frame, or -1 if we should use a frame pointer. */
+-static int
+-find_proc_framesize (CORE_ADDR pc)
++ This ABI also requires that the caller provide an argument pointer
++ to the callee, so we do that too. */
++
++CORE_ADDR
++hppa64_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
++ struct regcache *regcache, CORE_ADDR bp_addr,
++ int nargs, struct value **args, CORE_ADDR sp,
++ int struct_return, CORE_ADDR struct_addr)
+ {
+- struct unwind_table_entry *u;
+- struct minimal_symbol *msym_us;
++ /* NOTE: cagney/2004-02-27: This is a guess - its implemented by
++ reverse engineering testsuite failures. */
+
+- /* This may indicate a bug in our callers... */
+- if (pc == (CORE_ADDR) 0)
+- return -1;
++ /* Stack base address at which any pass-by-reference parameters are
++ stored. */
++ CORE_ADDR struct_end = 0;
++ /* Stack base address at which the first parameter is stored. */
++ CORE_ADDR param_end = 0;
+
+- u = find_unwind_entry (pc);
++ /* The inner most end of the stack after all the parameters have
++ been pushed. */
++ CORE_ADDR new_sp = 0;
+
+- if (!u)
++ /* Two passes. First pass computes the location of everything,
++ second pass writes the bytes out. */
++ int write_pass;
++ for (write_pass = 0; write_pass < 2; write_pass++)
+ {
+- if (pc_in_linker_stub (pc))
+- /* Linker stubs have a zero size frame. */
+- return 0;
+- else
+- return -1;
++ CORE_ADDR struct_ptr = 0;
++ CORE_ADDR param_ptr = 0;
++ int i;
++ for (i = 0; i < nargs; i++)
++ {
++ struct value *arg = args[i];
++ struct type *type = check_typedef (VALUE_TYPE (arg));
++ if ((TYPE_CODE (type) == TYPE_CODE_INT
++ || TYPE_CODE (type) == TYPE_CODE_ENUM)
++ && TYPE_LENGTH (type) <= 8)
++ {
++ /* Integer value store, right aligned. "unpack_long"
++ takes care of any sign-extension problems. */
++ param_ptr += 8;
++ if (write_pass)
++ {
++ ULONGEST val = unpack_long (type, VALUE_CONTENTS (arg));
++ int reg = 27 - param_ptr / 8;
++ write_memory_unsigned_integer (param_end - param_ptr,
++ val, 8);
++ if (reg >= 19)
++ regcache_cooked_write_unsigned (regcache, reg, val);
++ }
++ }
++ else
++ {
++ /* Small struct value, store left aligned? */
++ int reg;
++ if (TYPE_LENGTH (type) > 8)
++ {
++ param_ptr = align_up (param_ptr, 16);
++ reg = 26 - param_ptr / 8;
++ param_ptr += align_up (TYPE_LENGTH (type), 16);
++ }
++ else
++ {
++ param_ptr = align_up (param_ptr, 8);
++ reg = 26 - param_ptr / 8;
++ param_ptr += align_up (TYPE_LENGTH (type), 8);
++ }
++ if (write_pass)
++ {
++ int byte;
++ write_memory (param_end - param_ptr, VALUE_CONTENTS (arg),
++ TYPE_LENGTH (type));
++ for (byte = 0; byte < TYPE_LENGTH (type); byte += 8)
++ {
++ if (reg >= 19)
++ {
++ int len = min (8, TYPE_LENGTH (type) - byte);
++ regcache_cooked_write_part (regcache, reg, 0, len,
++ VALUE_CONTENTS (arg) + byte);
++ }
++ reg--;
++ }
++ }
++ }
++ }
++ /* Update the various stack pointers. */
++ if (!write_pass)
++ {
++ struct_end = sp + struct_ptr;
++ /* PARAM_PTR already accounts for all the arguments passed
++ by the user. However, the ABI mandates minimum stack
++ space allocations for outgoing arguments. The ABI also
++ mandates minimum stack alignments which we must
++ preserve. */
++ param_end = struct_end + max (align_up (param_ptr, 16), 64);
++ }
+ }
+
+- msym_us = lookup_minimal_symbol_by_pc (pc);
++ /* If a structure has to be returned, set up register 28 to hold its
++ address */
++ if (struct_return)
++ write_register (28, struct_addr);
+
+- /* If Save_SP is set, and we're not in an interrupt or signal caller,
+- then we have a frame pointer. Use it. */
+- if (u->Save_SP
+- && !pc_in_interrupt_handler (pc)
+- && msym_us
+- && !PC_IN_SIGTRAMP (pc, DEPRECATED_SYMBOL_NAME (msym_us)))
+- return -1;
++ /* Set the return address. */
++ regcache_cooked_write_unsigned (regcache, RP_REGNUM, bp_addr);
+
+- return u->Total_frame_size << 3;
+-}
++ /* Update the Stack Pointer. */
++ regcache_cooked_write_unsigned (regcache, SP_REGNUM, param_end + 64);
+
+-/* Return offset from sp at which rp is saved, or 0 if not saved. */
+-static int rp_saved (CORE_ADDR);
+-
+-static int
+-rp_saved (CORE_ADDR pc)
+-{
+- struct unwind_table_entry *u;
+-
+- /* A function at, and thus a return PC from, address 0? Not in HP-UX! */
+- if (pc == (CORE_ADDR) 0)
+- return 0;
+-
+- u = find_unwind_entry (pc);
+-
+- if (!u)
+- {
+- if (pc_in_linker_stub (pc))
+- /* This is the so-called RP'. */
+- return -24;
+- else
+- return 0;
+- }
+-
+- if (u->Save_RP)
+- return (TARGET_PTR_BIT == 64 ? -16 : -20);
+- else if (u->stub_unwind.stub_type != 0)
+- {
+- switch (u->stub_unwind.stub_type)
+- {
+- case EXPORT:
+- case IMPORT:
+- return -24;
+- case PARAMETER_RELOCATION:
+- return -8;
+- default:
+- return 0;
+- }
+- }
+- else
+- return 0;
+-}
+-
+-int
+-hppa_frameless_function_invocation (struct frame_info *frame)
+-{
+- struct unwind_table_entry *u;
+-
+- u = find_unwind_entry (get_frame_pc (frame));
+-
+- if (u == 0)
+- return 0;
+-
+- return (u->Total_frame_size == 0 && u->stub_unwind.stub_type == 0);
+-}
+-
+-/* Immediately after a function call, return the saved pc.
+- Can't go through the frames for this because on some machines
+- the new frame is not set up until the new function executes
+- some instructions. */
+-
+-CORE_ADDR
+-hppa_saved_pc_after_call (struct frame_info *frame)
+-{
+- int ret_regnum;
+- CORE_ADDR pc;
+- struct unwind_table_entry *u;
+-
+- ret_regnum = find_return_regnum (get_frame_pc (frame));
+- pc = read_register (ret_regnum) & ~0x3;
+-
+- /* If PC is in a linker stub, then we need to dig the address
+- the stub will return to out of the stack. */
+- u = find_unwind_entry (pc);
+- if (u && u->stub_unwind.stub_type != 0)
+- return DEPRECATED_FRAME_SAVED_PC (frame);
+- else
+- return pc;
+-}
+-
+-CORE_ADDR
+-hppa_frame_saved_pc (struct frame_info *frame)
+-{
+- CORE_ADDR pc = get_frame_pc (frame);
+- struct unwind_table_entry *u;
+- CORE_ADDR old_pc = 0;
+- int spun_around_loop = 0;
+- int rp_offset = 0;
+-
+- /* BSD, HPUX & OSF1 all lay out the hardware state in the same manner
+- at the base of the frame in an interrupt handler. Registers within
+- are saved in the exact same order as GDB numbers registers. How
+- convienent. */
+- if (pc_in_interrupt_handler (pc))
+- return read_memory_integer (get_frame_base (frame) + PC_REGNUM * 4,
+- TARGET_PTR_BIT / 8) & ~0x3;
+-
+- if ((get_frame_pc (frame) >= get_frame_base (frame)
+- && (get_frame_pc (frame)
+- <= (get_frame_base (frame)
+- /* A call dummy is sized in words, but it is actually a
+- series of instructions. Account for that scaling
+- factor. */
+- + ((DEPRECATED_REGISTER_SIZE / INSTRUCTION_SIZE)
+- * DEPRECATED_CALL_DUMMY_LENGTH)
+- /* Similarly we have to account for 64bit wide register
+- saves. */
+- + (32 * DEPRECATED_REGISTER_SIZE)
+- /* We always consider FP regs 8 bytes long. */
+- + (NUM_REGS - FP0_REGNUM) * 8
+- /* Similarly we have to account for 64bit wide register
+- saves. */
+- + (6 * DEPRECATED_REGISTER_SIZE)))))
+- {
+- return read_memory_integer ((get_frame_base (frame)
+- + (TARGET_PTR_BIT == 64 ? -16 : -20)),
+- TARGET_PTR_BIT / 8) & ~0x3;
+- }
+-
+-#ifdef FRAME_SAVED_PC_IN_SIGTRAMP
+- /* Deal with signal handler caller frames too. */
+- if ((get_frame_type (frame) == SIGTRAMP_FRAME))
+- {
+- CORE_ADDR rp;
+- FRAME_SAVED_PC_IN_SIGTRAMP (frame, &rp);
+- return rp & ~0x3;
+- }
+-#endif
+-
+- if (hppa_frameless_function_invocation (frame))
+- {
+- int ret_regnum;
+-
+- ret_regnum = find_return_regnum (pc);
+-
+- /* If the next frame is an interrupt frame or a signal
+- handler caller, then we need to look in the saved
+- register area to get the return pointer (the values
+- in the registers may not correspond to anything useful). */
+- if (get_next_frame (frame)
+- && ((get_frame_type (get_next_frame (frame)) == SIGTRAMP_FRAME)
+- || pc_in_interrupt_handler (get_frame_pc (get_next_frame (frame)))))
+- {
+- CORE_ADDR *saved_regs;
+- hppa_frame_init_saved_regs (get_next_frame (frame));
+- saved_regs = deprecated_get_frame_saved_regs (get_next_frame (frame));
+- if (read_memory_integer (saved_regs[FLAGS_REGNUM],
+- TARGET_PTR_BIT / 8) & 0x2)
+- {
+- pc = read_memory_integer (saved_regs[31],
+- TARGET_PTR_BIT / 8) & ~0x3;
+-
+- /* Syscalls are really two frames. The syscall stub itself
+- with a return pointer in %rp and the kernel call with
+- a return pointer in %r31. We return the %rp variant
+- if %r31 is the same as frame->pc. */
+- if (pc == get_frame_pc (frame))
+- pc = read_memory_integer (saved_regs[RP_REGNUM],
+- TARGET_PTR_BIT / 8) & ~0x3;
+- }
+- else
+- pc = read_memory_integer (saved_regs[RP_REGNUM],
+- TARGET_PTR_BIT / 8) & ~0x3;
+- }
+- else
+- pc = read_register (ret_regnum) & ~0x3;
+- }
+- else
+- {
+- spun_around_loop = 0;
+- old_pc = pc;
+-
+- restart:
+- rp_offset = rp_saved (pc);
+-
+- /* Similar to code in frameless function case. If the next
+- frame is a signal or interrupt handler, then dig the right
+- information out of the saved register info. */
+- if (rp_offset == 0
+- && get_next_frame (frame)
+- && ((get_frame_type (get_next_frame (frame)) == SIGTRAMP_FRAME)
+- || pc_in_interrupt_handler (get_frame_pc (get_next_frame (frame)))))
+- {
+- CORE_ADDR *saved_regs;
+- hppa_frame_init_saved_regs (get_next_frame (frame));
+- saved_regs = deprecated_get_frame_saved_regs (get_next_frame (frame));
+- if (read_memory_integer (saved_regs[FLAGS_REGNUM],
+- TARGET_PTR_BIT / 8) & 0x2)
+- {
+- pc = read_memory_integer (saved_regs[31],
+- TARGET_PTR_BIT / 8) & ~0x3;
+-
+- /* Syscalls are really two frames. The syscall stub itself
+- with a return pointer in %rp and the kernel call with
+- a return pointer in %r31. We return the %rp variant
+- if %r31 is the same as frame->pc. */
+- if (pc == get_frame_pc (frame))
+- pc = read_memory_integer (saved_regs[RP_REGNUM],
+- TARGET_PTR_BIT / 8) & ~0x3;
+- }
+- else
+- pc = read_memory_integer (saved_regs[RP_REGNUM],
+- TARGET_PTR_BIT / 8) & ~0x3;
+- }
+- else if (rp_offset == 0)
+- {
+- old_pc = pc;
+- pc = read_register (RP_REGNUM) & ~0x3;
+- }
+- else
+- {
+- old_pc = pc;
+- pc = read_memory_integer (get_frame_base (frame) + rp_offset,
+- TARGET_PTR_BIT / 8) & ~0x3;
+- }
+- }
+-
+- /* If PC is inside a linker stub, then dig out the address the stub
+- will return to.
+-
+- Don't do this for long branch stubs. Why? For some unknown reason
+- _start is marked as a long branch stub in hpux10. */
+- u = find_unwind_entry (pc);
+- if (u && u->stub_unwind.stub_type != 0
+- && u->stub_unwind.stub_type != LONG_BRANCH)
+- {
+- unsigned int insn;
+-
+- /* If this is a dynamic executable, and we're in a signal handler,
+- then the call chain will eventually point us into the stub for
+- _sigreturn. Unlike most cases, we'll be pointed to the branch
+- to the real sigreturn rather than the code after the real branch!.
+-
+- Else, try to dig the address the stub will return to in the normal
+- fashion. */
+- insn = read_memory_integer (pc, 4);
+- if ((insn & 0xfc00e000) == 0xe8000000)
+- return (pc + extract_17 (insn) + 8) & ~0x3;
+- else
+- {
+- if (old_pc == pc)
+- spun_around_loop++;
+-
+- if (spun_around_loop > 1)
+- {
+- /* We're just about to go around the loop again with
+- no more hope of success. Die. */
+- error ("Unable to find return pc for this frame");
+- }
+- else
+- goto restart;
+- }
+- }
+-
+- return pc;
+-}
+-
+-/* We need to correct the PC and the FP for the outermost frame when we are
+- in a system call. */
+-
+-void
+-hppa_init_extra_frame_info (int fromleaf, struct frame_info *frame)
+-{
+- int flags;
+- int framesize;
+-
+- if (get_next_frame (frame) && !fromleaf)
+- return;
+-
+- /* If the next frame represents a frameless function invocation then
+- we have to do some adjustments that are normally done by
+- DEPRECATED_FRAME_CHAIN. (DEPRECATED_FRAME_CHAIN is not called in
+- this case.) */
+- if (fromleaf)
+- {
+- /* Find the framesize of *this* frame without peeking at the PC
+- in the current frame structure (it isn't set yet). */
+- framesize = find_proc_framesize (DEPRECATED_FRAME_SAVED_PC (get_next_frame (frame)));
+-
+- /* Now adjust our base frame accordingly. If we have a frame pointer
+- use it, else subtract the size of this frame from the current
+- frame. (we always want frame->frame to point at the lowest address
+- in the frame). */
+- if (framesize == -1)
+- deprecated_update_frame_base_hack (frame, deprecated_read_fp ());
+- else
+- deprecated_update_frame_base_hack (frame, get_frame_base (frame) - framesize);
+- return;
+- }
+-
+- flags = read_register (FLAGS_REGNUM);
+- if (flags & 2) /* In system call? */
+- deprecated_update_frame_pc_hack (frame, read_register (31) & ~0x3);
+-
+- /* The outermost frame is always derived from PC-framesize
+-
+- One might think frameless innermost frames should have
+- a frame->frame that is the same as the parent's frame->frame.
+- That is wrong; frame->frame in that case should be the *high*
+- address of the parent's frame. It's complicated as hell to
+- explain, but the parent *always* creates some stack space for
+- the child. So the child actually does have a frame of some
+- sorts, and its base is the high address in its parent's frame. */
+- framesize = find_proc_framesize (get_frame_pc (frame));
+- if (framesize == -1)
+- deprecated_update_frame_base_hack (frame, deprecated_read_fp ());
+- else
+- deprecated_update_frame_base_hack (frame, read_register (SP_REGNUM) - framesize);
+-}
+-
+-/* Given a GDB frame, determine the address of the calling function's
+- frame. This will be used to create a new GDB frame struct, and
+- then DEPRECATED_INIT_EXTRA_FRAME_INFO and DEPRECATED_INIT_FRAME_PC
+- will be called for the new frame.
+-
+- This may involve searching through prologues for several functions
+- at boundaries where GCC calls HP C code, or where code which has
+- a frame pointer calls code without a frame pointer. */
+-
+-CORE_ADDR
+-hppa_frame_chain (struct frame_info *frame)
+-{
+- int my_framesize, caller_framesize;
+- struct unwind_table_entry *u;
+- CORE_ADDR frame_base;
+- struct frame_info *tmp_frame;
+-
+- /* A frame in the current frame list, or zero. */
+- struct frame_info *saved_regs_frame = 0;
+- /* Where the registers were saved in saved_regs_frame. If
+- saved_regs_frame is zero, this is garbage. */
+- CORE_ADDR *saved_regs = NULL;
+-
+- CORE_ADDR caller_pc;
+-
+- struct minimal_symbol *min_frame_symbol;
+- struct symbol *frame_symbol;
+- char *frame_symbol_name;
+-
+- /* If this is a threaded application, and we see the
+- routine "__pthread_exit", treat it as the stack root
+- for this thread. */
+- min_frame_symbol = lookup_minimal_symbol_by_pc (get_frame_pc (frame));
+- frame_symbol = find_pc_function (get_frame_pc (frame));
+-
+- if ((min_frame_symbol != 0) /* && (frame_symbol == 0) */ )
+- {
+- /* The test above for "no user function name" would defend
+- against the slim likelihood that a user might define a
+- routine named "__pthread_exit" and then try to debug it.
+-
+- If it weren't commented out, and you tried to debug the
+- pthread library itself, you'd get errors.
+-
+- So for today, we don't make that check. */
+- frame_symbol_name = DEPRECATED_SYMBOL_NAME (min_frame_symbol);
+- if (frame_symbol_name != 0)
+- {
+- if (0 == strncmp (frame_symbol_name,
+- THREAD_INITIAL_FRAME_SYMBOL,
+- THREAD_INITIAL_FRAME_SYM_LEN))
+- {
+- /* Pretend we've reached the bottom of the stack. */
+- return (CORE_ADDR) 0;
+- }
+- }
+- } /* End of hacky code for threads. */
+-
+- /* Handle HPUX, BSD, and OSF1 style interrupt frames first. These
+- are easy; at *sp we have a full save state strucutre which we can
+- pull the old stack pointer from. Also see frame_saved_pc for
+- code to dig a saved PC out of the save state structure. */
+- if (pc_in_interrupt_handler (get_frame_pc (frame)))
+- frame_base = read_memory_integer (get_frame_base (frame) + SP_REGNUM * 4,
+- TARGET_PTR_BIT / 8);
+-#ifdef FRAME_BASE_BEFORE_SIGTRAMP
+- else if ((get_frame_type (frame) == SIGTRAMP_FRAME))
+- {
+- FRAME_BASE_BEFORE_SIGTRAMP (frame, &frame_base);
+- }
+-#endif
+- else
+- frame_base = get_frame_base (frame);
+-
+- /* Get frame sizes for the current frame and the frame of the
+- caller. */
+- my_framesize = find_proc_framesize (get_frame_pc (frame));
+- caller_pc = DEPRECATED_FRAME_SAVED_PC (frame);
+-
+- /* If we can't determine the caller's PC, then it's not likely we can
+- really determine anything meaningful about its frame. We'll consider
+- this to be stack bottom. */
+- if (caller_pc == (CORE_ADDR) 0)
+- return (CORE_ADDR) 0;
+-
+- caller_framesize = find_proc_framesize (DEPRECATED_FRAME_SAVED_PC (frame));
+-
+- /* If caller does not have a frame pointer, then its frame
+- can be found at current_frame - caller_framesize. */
+- if (caller_framesize != -1)
+- {
+- return frame_base - caller_framesize;
+- }
+- /* Both caller and callee have frame pointers and are GCC compiled
+- (SAVE_SP bit in unwind descriptor is on for both functions.
+- The previous frame pointer is found at the top of the current frame. */
+- if (caller_framesize == -1 && my_framesize == -1)
+- {
+- return read_memory_integer (frame_base, TARGET_PTR_BIT / 8);
+- }
+- /* Caller has a frame pointer, but callee does not. This is a little
+- more difficult as GCC and HP C lay out locals and callee register save
+- areas very differently.
+-
+- The previous frame pointer could be in a register, or in one of
+- several areas on the stack.
+-
+- Walk from the current frame to the innermost frame examining
+- unwind descriptors to determine if %r3 ever gets saved into the
+- stack. If so return whatever value got saved into the stack.
+- If it was never saved in the stack, then the value in %r3 is still
+- valid, so use it.
+-
+- We use information from unwind descriptors to determine if %r3
+- is saved into the stack (Entry_GR field has this information). */
+-
+- for (tmp_frame = frame; tmp_frame; tmp_frame = get_next_frame (tmp_frame))
+- {
+- u = find_unwind_entry (get_frame_pc (tmp_frame));
+-
+- if (!u)
+- {
+- /* We could find this information by examining prologues. I don't
+- think anyone has actually written any tools (not even "strip")
+- which leave them out of an executable, so maybe this is a moot
+- point. */
+- /* ??rehrauer: Actually, it's quite possible to stepi your way into
+- code that doesn't have unwind entries. For example, stepping into
+- the dynamic linker will give you a PC that has none. Thus, I've
+- disabled this warning. */
+-#if 0
+- warning ("Unable to find unwind for PC 0x%x -- Help!", get_frame_pc (tmp_frame));
+-#endif
+- return (CORE_ADDR) 0;
+- }
+-
+- if (u->Save_SP
+- || (get_frame_type (tmp_frame) == SIGTRAMP_FRAME)
+- || pc_in_interrupt_handler (get_frame_pc (tmp_frame)))
+- break;
+-
+- /* Entry_GR specifies the number of callee-saved general registers
+- saved in the stack. It starts at %r3, so %r3 would be 1. */
+- if (u->Entry_GR >= 1)
+- {
+- /* The unwind entry claims that r3 is saved here. However,
+- in optimized code, GCC often doesn't actually save r3.
+- We'll discover this if we look at the prologue. */
+- hppa_frame_init_saved_regs (tmp_frame);
+- saved_regs = deprecated_get_frame_saved_regs (tmp_frame);
+- saved_regs_frame = tmp_frame;
+-
+- /* If we have an address for r3, that's good. */
+- if (saved_regs[DEPRECATED_FP_REGNUM])
+- break;
+- }
+- }
+-
+- if (tmp_frame)
+- {
+- /* We may have walked down the chain into a function with a frame
+- pointer. */
+- if (u->Save_SP
+- && !(get_frame_type (tmp_frame) == SIGTRAMP_FRAME)
+- && !pc_in_interrupt_handler (get_frame_pc (tmp_frame)))
+- {
+- return read_memory_integer (get_frame_base (tmp_frame), TARGET_PTR_BIT / 8);
+- }
+- /* %r3 was saved somewhere in the stack. Dig it out. */
+- else
+- {
+- /* Sick.
+-
+- For optimization purposes many kernels don't have the
+- callee saved registers into the save_state structure upon
+- entry into the kernel for a syscall; the optimization
+- is usually turned off if the process is being traced so
+- that the debugger can get full register state for the
+- process.
+-
+- This scheme works well except for two cases:
+-
+- * Attaching to a process when the process is in the
+- kernel performing a system call (debugger can't get
+- full register state for the inferior process since
+- the process wasn't being traced when it entered the
+- system call).
+-
+- * Register state is not complete if the system call
+- causes the process to core dump.
+-
+-
+- The following heinous code is an attempt to deal with
+- the lack of register state in a core dump. It will
+- fail miserably if the function which performs the
+- system call has a variable sized stack frame. */
+-
+- if (tmp_frame != saved_regs_frame)
+- {
+- hppa_frame_init_saved_regs (tmp_frame);
+- saved_regs = deprecated_get_frame_saved_regs (tmp_frame);
+- }
+-
+- /* Abominable hack. */
+- if (current_target.to_has_execution == 0
+- && ((saved_regs[FLAGS_REGNUM]
+- && (read_memory_integer (saved_regs[FLAGS_REGNUM],
+- TARGET_PTR_BIT / 8)
+- & 0x2))
+- || (saved_regs[FLAGS_REGNUM] == 0
+- && read_register (FLAGS_REGNUM) & 0x2)))
+- {
+- u = find_unwind_entry (DEPRECATED_FRAME_SAVED_PC (frame));
+- if (!u)
+- {
+- return read_memory_integer (saved_regs[DEPRECATED_FP_REGNUM],
+- TARGET_PTR_BIT / 8);
+- }
+- else
+- {
+- return frame_base - (u->Total_frame_size << 3);
+- }
+- }
+-
+- return read_memory_integer (saved_regs[DEPRECATED_FP_REGNUM],
+- TARGET_PTR_BIT / 8);
+- }
+- }
+- else
+- {
+- /* Get the innermost frame. */
+- tmp_frame = frame;
+- while (get_next_frame (tmp_frame) != NULL)
+- tmp_frame = get_next_frame (tmp_frame);
+-
+- if (tmp_frame != saved_regs_frame)
+- {
+- hppa_frame_init_saved_regs (tmp_frame);
+- saved_regs = deprecated_get_frame_saved_regs (tmp_frame);
+- }
+-
+- /* Abominable hack. See above. */
+- if (current_target.to_has_execution == 0
+- && ((saved_regs[FLAGS_REGNUM]
+- && (read_memory_integer (saved_regs[FLAGS_REGNUM],
+- TARGET_PTR_BIT / 8)
+- & 0x2))
+- || (saved_regs[FLAGS_REGNUM] == 0
+- && read_register (FLAGS_REGNUM) & 0x2)))
+- {
+- u = find_unwind_entry (DEPRECATED_FRAME_SAVED_PC (frame));
+- if (!u)
+- {
+- return read_memory_integer (saved_regs[DEPRECATED_FP_REGNUM],
+- TARGET_PTR_BIT / 8);
+- }
+- else
+- {
+- return frame_base - (u->Total_frame_size << 3);
+- }
+- }
+-
+- /* The value in %r3 was never saved into the stack (thus %r3 still
+- holds the value of the previous frame pointer). */
+- return deprecated_read_fp ();
+- }
+-}
+-
+-
+-/* To see if a frame chain is valid, see if the caller looks like it
+- was compiled with gcc. */
+-
+-int
+-hppa_frame_chain_valid (CORE_ADDR chain, struct frame_info *thisframe)
+-{
+- struct minimal_symbol *msym_us;
+- struct minimal_symbol *msym_start;
+- struct unwind_table_entry *u, *next_u = NULL;
+- struct frame_info *next;
+-
+- u = find_unwind_entry (get_frame_pc (thisframe));
+-
+- if (u == NULL)
+- return 1;
+-
+- /* We can't just check that the same of msym_us is "_start", because
+- someone idiotically decided that they were going to make a Ltext_end
+- symbol with the same address. This Ltext_end symbol is totally
+- indistinguishable (as nearly as I can tell) from the symbol for a function
+- which is (legitimately, since it is in the user's namespace)
+- named Ltext_end, so we can't just ignore it. */
+- msym_us = lookup_minimal_symbol_by_pc (DEPRECATED_FRAME_SAVED_PC (thisframe));
+- msym_start = lookup_minimal_symbol ("_start", NULL, NULL);
+- if (msym_us
+- && msym_start
+- && SYMBOL_VALUE_ADDRESS (msym_us) == SYMBOL_VALUE_ADDRESS (msym_start))
+- return 0;
+-
+- /* Grrrr. Some new idiot decided that they don't want _start for the
+- PRO configurations; $START$ calls main directly.... Deal with it. */
+- msym_start = lookup_minimal_symbol ("$START$", NULL, NULL);
+- if (msym_us
+- && msym_start
+- && SYMBOL_VALUE_ADDRESS (msym_us) == SYMBOL_VALUE_ADDRESS (msym_start))
+- return 0;
+-
+- next = get_next_frame (thisframe);
+- if (next)
+- next_u = find_unwind_entry (get_frame_pc (next));
+-
+- /* If this frame does not save SP, has no stack, isn't a stub,
+- and doesn't "call" an interrupt routine or signal handler caller,
+- then its not valid. */
+- if (u->Save_SP || u->Total_frame_size || u->stub_unwind.stub_type != 0
+- || (get_next_frame (thisframe) && (get_frame_type (get_next_frame (thisframe)) == SIGTRAMP_FRAME))
+- || (next_u && next_u->HP_UX_interrupt_marker))
+- return 1;
+-
+- if (pc_in_linker_stub (get_frame_pc (thisframe)))
+- return 1;
+-
+- return 0;
+-}
+-
+-/* These functions deal with saving and restoring register state
+- around a function call in the inferior. They keep the stack
+- double-word aligned; eventually, on an hp700, the stack will have
+- to be aligned to a 64-byte boundary. */
+-
+-void
+-hppa_push_dummy_frame (void)
+-{
+- CORE_ADDR sp, pc, pcspace;
+- int regnum;
+- CORE_ADDR int_buffer;
+- double freg_buffer;
+-
+- pc = hppa_target_read_pc (inferior_ptid);
+- int_buffer = read_register (FLAGS_REGNUM);
+- if (int_buffer & 0x2)
+- {
+- const unsigned int sid = (pc >> 30) & 0x3;
+- if (sid == 0)
+- pcspace = read_register (SR4_REGNUM);
+- else
+- pcspace = read_register (SR4_REGNUM + 4 + sid);
+- }
+- else
+- pcspace = read_register (PCSQ_HEAD_REGNUM);
+-
+- /* Space for "arguments"; the RP goes in here. */
+- sp = read_register (SP_REGNUM) + 48;
+- int_buffer = read_register (RP_REGNUM) | 0x3;
+-
+- /* The 32bit and 64bit ABIs save the return pointer into different
+- stack slots. */
+- if (DEPRECATED_REGISTER_SIZE == 8)
+- write_memory (sp - 16, (char *) &int_buffer, DEPRECATED_REGISTER_SIZE);
+- else
+- write_memory (sp - 20, (char *) &int_buffer, DEPRECATED_REGISTER_SIZE);
+-
+- int_buffer = deprecated_read_fp ();
+- write_memory (sp, (char *) &int_buffer, DEPRECATED_REGISTER_SIZE);
+-
+- write_register (DEPRECATED_FP_REGNUM, sp);
+-
+- sp += 2 * DEPRECATED_REGISTER_SIZE;
+-
+- for (regnum = 1; regnum < 32; regnum++)
+- if (regnum != RP_REGNUM && regnum != DEPRECATED_FP_REGNUM)
+- sp = push_word (sp, read_register (regnum));
+-
+- /* This is not necessary for the 64bit ABI. In fact it is dangerous. */
+- if (DEPRECATED_REGISTER_SIZE != 8)
+- sp += 4;
+-
+- for (regnum = FP0_REGNUM; regnum < NUM_REGS; regnum++)
+- {
+- deprecated_read_register_bytes (DEPRECATED_REGISTER_BYTE (regnum),
+- (char *) &freg_buffer, 8);
+- sp = push_bytes (sp, (char *) &freg_buffer, 8);
+- }
+- sp = push_word (sp, read_register (IPSW_REGNUM));
+- sp = push_word (sp, read_register (SAR_REGNUM));
+- sp = push_word (sp, pc);
+- sp = push_word (sp, pcspace);
+- sp = push_word (sp, pc + 4);
+- sp = push_word (sp, pcspace);
+- write_register (SP_REGNUM, sp);
+-}
+-
+-static void
+-find_dummy_frame_regs (struct frame_info *frame,
+- CORE_ADDR frame_saved_regs[])
+-{
+- CORE_ADDR fp = get_frame_base (frame);
+- int i;
+-
+- /* The 32bit and 64bit ABIs save RP into different locations. */
+- if (DEPRECATED_REGISTER_SIZE == 8)
+- frame_saved_regs[RP_REGNUM] = (fp - 16) & ~0x3;
+- else
+- frame_saved_regs[RP_REGNUM] = (fp - 20) & ~0x3;
+-
+- frame_saved_regs[DEPRECATED_FP_REGNUM] = fp;
+-
+- frame_saved_regs[1] = fp + (2 * DEPRECATED_REGISTER_SIZE);
+-
+- for (fp += 3 * DEPRECATED_REGISTER_SIZE, i = 3; i < 32; i++)
+- {
+- if (i != DEPRECATED_FP_REGNUM)
+- {
+- frame_saved_regs[i] = fp;
+- fp += DEPRECATED_REGISTER_SIZE;
+- }
+- }
+-
+- /* This is not necessary or desirable for the 64bit ABI. */
+- if (DEPRECATED_REGISTER_SIZE != 8)
+- fp += 4;
+-
+- for (i = FP0_REGNUM; i < NUM_REGS; i++, fp += 8)
+- frame_saved_regs[i] = fp;
+-
+- frame_saved_regs[IPSW_REGNUM] = fp;
+- frame_saved_regs[SAR_REGNUM] = fp + DEPRECATED_REGISTER_SIZE;
+- frame_saved_regs[PCOQ_HEAD_REGNUM] = fp + 2 * DEPRECATED_REGISTER_SIZE;
+- frame_saved_regs[PCSQ_HEAD_REGNUM] = fp + 3 * DEPRECATED_REGISTER_SIZE;
+- frame_saved_regs[PCOQ_TAIL_REGNUM] = fp + 4 * DEPRECATED_REGISTER_SIZE;
+- frame_saved_regs[PCSQ_TAIL_REGNUM] = fp + 5 * DEPRECATED_REGISTER_SIZE;
+-}
+-
+-void
+-hppa_pop_frame (void)
+-{
+- struct frame_info *frame = get_current_frame ();
+- CORE_ADDR fp, npc, target_pc;
+- int regnum;
+- CORE_ADDR *fsr;
+- double freg_buffer;
+-
+- fp = get_frame_base (frame);
+- hppa_frame_init_saved_regs (frame);
+- fsr = deprecated_get_frame_saved_regs (frame);
+-
+-#ifndef NO_PC_SPACE_QUEUE_RESTORE
+- if (fsr[IPSW_REGNUM]) /* Restoring a call dummy frame */
+- restore_pc_queue (fsr);
+-#endif
+-
+- for (regnum = 31; regnum > 0; regnum--)
+- if (fsr[regnum])
+- write_register (regnum, read_memory_integer (fsr[regnum],
+- DEPRECATED_REGISTER_SIZE));
+-
+- for (regnum = NUM_REGS - 1; regnum >= FP0_REGNUM; regnum--)
+- if (fsr[regnum])
+- {
+- read_memory (fsr[regnum], (char *) &freg_buffer, 8);
+- deprecated_write_register_bytes (DEPRECATED_REGISTER_BYTE (regnum),
+- (char *) &freg_buffer, 8);
+- }
+-
+- if (fsr[IPSW_REGNUM])
+- write_register (IPSW_REGNUM,
+- read_memory_integer (fsr[IPSW_REGNUM],
+- DEPRECATED_REGISTER_SIZE));
+-
+- if (fsr[SAR_REGNUM])
+- write_register (SAR_REGNUM,
+- read_memory_integer (fsr[SAR_REGNUM],
+- DEPRECATED_REGISTER_SIZE));
+-
+- /* If the PC was explicitly saved, then just restore it. */
+- if (fsr[PCOQ_TAIL_REGNUM])
+- {
+- npc = read_memory_integer (fsr[PCOQ_TAIL_REGNUM],
+- DEPRECATED_REGISTER_SIZE);
+- write_register (PCOQ_TAIL_REGNUM, npc);
+- }
+- /* Else use the value in %rp to set the new PC. */
+- else
+- {
+- npc = read_register (RP_REGNUM);
+- write_pc (npc);
+- }
+-
+- write_register (DEPRECATED_FP_REGNUM, read_memory_integer (fp, DEPRECATED_REGISTER_SIZE));
+-
+- if (fsr[IPSW_REGNUM]) /* call dummy */
+- write_register (SP_REGNUM, fp - 48);
+- else
+- write_register (SP_REGNUM, fp);
+-
+- /* The PC we just restored may be inside a return trampoline. If so
+- we want to restart the inferior and run it through the trampoline.
+-
+- Do this by setting a momentary breakpoint at the location the
+- trampoline returns to.
+-
+- Don't skip through the trampoline if we're popping a dummy frame. */
+- target_pc = SKIP_TRAMPOLINE_CODE (npc & ~0x3) & ~0x3;
+- if (target_pc && !fsr[IPSW_REGNUM])
+- {
+- struct symtab_and_line sal;
+- struct breakpoint *breakpoint;
+- struct cleanup *old_chain;
+-
+- /* Set up our breakpoint. Set it to be silent as the MI code
+- for "return_command" will print the frame we returned to. */
+- sal = find_pc_line (target_pc, 0);
+- sal.pc = target_pc;
+- breakpoint = set_momentary_breakpoint (sal, null_frame_id, bp_finish);
+- breakpoint->silent = 1;
+-
+- /* So we can clean things up. */
+- old_chain = make_cleanup_delete_breakpoint (breakpoint);
+-
+- /* Start up the inferior. */
+- clear_proceed_status ();
+- proceed_to_finish = 1;
+- proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 0);
+-
+- /* Perform our cleanups. */
+- do_cleanups (old_chain);
+- }
+- flush_cached_frames ();
+-}
+-
+-/* After returning to a dummy on the stack, restore the instruction
+- queue space registers. */
+-
+-static int
+-restore_pc_queue (CORE_ADDR *fsr)
+-{
+- CORE_ADDR pc = read_pc ();
+- CORE_ADDR new_pc = read_memory_integer (fsr[PCOQ_HEAD_REGNUM],
+- TARGET_PTR_BIT / 8);
+- struct target_waitstatus w;
+- int insn_count;
+-
+- /* Advance past break instruction in the call dummy. */
+- write_register (PCOQ_HEAD_REGNUM, pc + 4);
+- write_register (PCOQ_TAIL_REGNUM, pc + 8);
+-
+- /* HPUX doesn't let us set the space registers or the space
+- registers of the PC queue through ptrace. Boo, hiss.
+- Conveniently, the call dummy has this sequence of instructions
+- after the break:
+- mtsp r21, sr0
+- ble,n 0(sr0, r22)
+-
+- So, load up the registers and single step until we are in the
+- right place. */
+-
+- write_register (21, read_memory_integer (fsr[PCSQ_HEAD_REGNUM],
+- DEPRECATED_REGISTER_SIZE));
+- write_register (22, new_pc);
+-
+- for (insn_count = 0; insn_count < 3; insn_count++)
+- {
+- /* FIXME: What if the inferior gets a signal right now? Want to
+- merge this into wait_for_inferior (as a special kind of
+- watchpoint? By setting a breakpoint at the end? Is there
+- any other choice? Is there *any* way to do this stuff with
+- ptrace() or some equivalent?). */
+- resume (1, 0);
+- target_wait (inferior_ptid, &w);
+-
+- if (w.kind == TARGET_WAITKIND_SIGNALLED)
+- {
+- stop_signal = w.value.sig;
+- terminal_ours_for_output ();
+- printf_unfiltered ("\nProgram terminated with signal %s, %s.\n",
+- target_signal_to_name (stop_signal),
+- target_signal_to_string (stop_signal));
+- gdb_flush (gdb_stdout);
+- return 0;
+- }
+- }
+- target_terminal_ours ();
+- target_fetch_registers (-1);
+- return 1;
+-}
+-
+-
+-#ifdef PA20W_CALLING_CONVENTIONS
+-
+-/* This function pushes a stack frame with arguments as part of the
+- inferior function calling mechanism.
+-
+- This is the version for the PA64, in which later arguments appear
+- at higher addresses. (The stack always grows towards higher
+- addresses.)
+-
+- We simply allocate the appropriate amount of stack space and put
+- arguments into their proper slots. The call dummy code will copy
+- arguments into registers as needed by the ABI.
+-
+- This ABI also requires that the caller provide an argument pointer
+- to the callee, so we do that too. */
+-
+-CORE_ADDR
+-hppa_push_arguments (int nargs, struct value **args, CORE_ADDR sp,
+- int struct_return, CORE_ADDR struct_addr)
+-{
+- /* array of arguments' offsets */
+- int *offset = (int *) alloca (nargs * sizeof (int));
+-
+- /* array of arguments' lengths: real lengths in bytes, not aligned to
+- word size */
+- int *lengths = (int *) alloca (nargs * sizeof (int));
+-
+- /* The value of SP as it was passed into this function after
+- aligning. */
+- CORE_ADDR orig_sp = DEPRECATED_STACK_ALIGN (sp);
+-
+- /* The number of stack bytes occupied by the current argument. */
+- int bytes_reserved;
+-
+- /* The total number of bytes reserved for the arguments. */
+- int cum_bytes_reserved = 0;
+-
+- /* Similarly, but aligned. */
+- int cum_bytes_aligned = 0;
+- int i;
+-
+- /* Iterate over each argument provided by the user. */
+- for (i = 0; i < nargs; i++)
+- {
+- struct type *arg_type = VALUE_TYPE (args[i]);
+-
+- /* Integral scalar values smaller than a register are padded on
+- the left. We do this by promoting them to full-width,
+- although the ABI says to pad them with garbage. */
+- if (is_integral_type (arg_type)
+- && TYPE_LENGTH (arg_type) < DEPRECATED_REGISTER_SIZE)
+- {
+- args[i] = value_cast ((TYPE_UNSIGNED (arg_type)
+- ? builtin_type_unsigned_long
+- : builtin_type_long),
+- args[i]);
+- arg_type = VALUE_TYPE (args[i]);
+- }
+-
+- lengths[i] = TYPE_LENGTH (arg_type);
+-
+- /* Align the size of the argument to the word size for this
+- target. */
+- bytes_reserved = (lengths[i] + DEPRECATED_REGISTER_SIZE - 1) & -DEPRECATED_REGISTER_SIZE;
+-
+- offset[i] = cum_bytes_reserved;
+-
+- /* Aggregates larger than eight bytes (the only types larger
+- than eight bytes we have) are aligned on a 16-byte boundary,
+- possibly padded on the right with garbage. This may leave an
+- empty word on the stack, and thus an unused register, as per
+- the ABI. */
+- if (bytes_reserved > 8)
+- {
+- /* Round up the offset to a multiple of two slots. */
+- int new_offset = ((offset[i] + 2*DEPRECATED_REGISTER_SIZE-1)
+- & -(2*DEPRECATED_REGISTER_SIZE));
+-
+- /* Note the space we've wasted, if any. */
+- bytes_reserved += new_offset - offset[i];
+- offset[i] = new_offset;
+- }
+-
+- cum_bytes_reserved += bytes_reserved;
+- }
+-
+- /* CUM_BYTES_RESERVED already accounts for all the arguments
+- passed by the user. However, the ABIs mandate minimum stack space
+- allocations for outgoing arguments.
+-
+- The ABIs also mandate minimum stack alignments which we must
+- preserve. */
+- cum_bytes_aligned = DEPRECATED_STACK_ALIGN (cum_bytes_reserved);
+- sp += max (cum_bytes_aligned, REG_PARM_STACK_SPACE);
+-
+- /* Now write each of the args at the proper offset down the stack. */
+- for (i = 0; i < nargs; i++)
+- write_memory (orig_sp + offset[i], VALUE_CONTENTS (args[i]), lengths[i]);
+-
+- /* If a structure has to be returned, set up register 28 to hold its
+- address */
+- if (struct_return)
+- write_register (28, struct_addr);
+-
+- /* For the PA64 we must pass a pointer to the outgoing argument list.
+- The ABI mandates that the pointer should point to the first byte of
+- storage beyond the register flushback area.
+-
+- However, the call dummy expects the outgoing argument pointer to
+- be passed in register %r4. */
+- write_register (4, orig_sp + REG_PARM_STACK_SPACE);
+-
+- /* ?!? This needs further work. We need to set up the global data
+- pointer for this procedure. This assumes the same global pointer
+- for every procedure. The call dummy expects the dp value to
+- be passed in register %r6. */
+- write_register (6, read_register (27));
+-
+- /* The stack will have 64 bytes of additional space for a frame marker. */
+- return sp + 64;
+-}
+-
+-#else
+-
+-/* This function pushes a stack frame with arguments as part of the
+- inferior function calling mechanism.
+-
+- This is the version of the function for the 32-bit PA machines, in
+- which later arguments appear at lower addresses. (The stack always
+- grows towards higher addresses.)
+-
+- We simply allocate the appropriate amount of stack space and put
+- arguments into their proper slots. The call dummy code will copy
+- arguments into registers as needed by the ABI. */
+-
+-CORE_ADDR
+-hppa_push_arguments (int nargs, struct value **args, CORE_ADDR sp,
+- int struct_return, CORE_ADDR struct_addr)
+-{
+- /* array of arguments' offsets */
+- int *offset = (int *) alloca (nargs * sizeof (int));
+-
+- /* array of arguments' lengths: real lengths in bytes, not aligned to
+- word size */
+- int *lengths = (int *) alloca (nargs * sizeof (int));
+-
+- /* The number of stack bytes occupied by the current argument. */
+- int bytes_reserved;
+-
+- /* The total number of bytes reserved for the arguments. */
+- int cum_bytes_reserved = 0;
+-
+- /* Similarly, but aligned. */
+- int cum_bytes_aligned = 0;
+- int i;
+-
+- /* Iterate over each argument provided by the user. */
+- for (i = 0; i < nargs; i++)
+- {
+- lengths[i] = TYPE_LENGTH (VALUE_TYPE (args[i]));
+-
+- /* Align the size of the argument to the word size for this
+- target. */
+- bytes_reserved = (lengths[i] + DEPRECATED_REGISTER_SIZE - 1) & -DEPRECATED_REGISTER_SIZE;
+-
+- offset[i] = (cum_bytes_reserved
+- + (lengths[i] > 4 ? bytes_reserved : lengths[i]));
+-
+- /* If the argument is a double word argument, then it needs to be
+- double word aligned. */
+- if ((bytes_reserved == 2 * DEPRECATED_REGISTER_SIZE)
+- && (offset[i] % 2 * DEPRECATED_REGISTER_SIZE))
+- {
+- int new_offset = 0;
+- /* BYTES_RESERVED is already aligned to the word, so we put
+- the argument at one word more down the stack.
+-
+- This will leave one empty word on the stack, and one unused
+- register as mandated by the ABI. */
+- new_offset = ((offset[i] + 2 * DEPRECATED_REGISTER_SIZE - 1)
+- & -(2 * DEPRECATED_REGISTER_SIZE));
+-
+- if ((new_offset - offset[i]) >= 2 * DEPRECATED_REGISTER_SIZE)
+- {
+- bytes_reserved += DEPRECATED_REGISTER_SIZE;
+- offset[i] += DEPRECATED_REGISTER_SIZE;
+- }
+- }
+-
+- cum_bytes_reserved += bytes_reserved;
+-
+- }
+-
+- /* CUM_BYTES_RESERVED already accounts for all the arguments passed
+- by the user. However, the ABI mandates minimum stack space
+- allocations for outgoing arguments.
+-
+- The ABI also mandates minimum stack alignments which we must
+- preserve. */
+- cum_bytes_aligned = DEPRECATED_STACK_ALIGN (cum_bytes_reserved);
+- sp += max (cum_bytes_aligned, REG_PARM_STACK_SPACE);
+-
+- /* Now write each of the args at the proper offset down the stack.
+- ?!? We need to promote values to a full register instead of skipping
+- words in the stack. */
+- for (i = 0; i < nargs; i++)
+- write_memory (sp - offset[i], VALUE_CONTENTS (args[i]), lengths[i]);
+-
+- /* If a structure has to be returned, set up register 28 to hold its
+- address */
+- if (struct_return)
+- write_register (28, struct_addr);
+-
+- /* The stack will have 32 bytes of additional space for a frame marker. */
+- return sp + 32;
+-}
+-
+-#endif
+-
+-/* This function pushes a stack frame with arguments as part of the
+- inferior function calling mechanism.
+-
+- This is the version of the function for the 32-bit PA machines, in
+- which later arguments appear at lower addresses. (The stack always
+- grows towards higher addresses.)
+-
+- We simply allocate the appropriate amount of stack space and put
+- arguments into their proper slots. */
+-
+-CORE_ADDR
+-hppa32_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
+- struct regcache *regcache, CORE_ADDR bp_addr,
+- int nargs, struct value **args, CORE_ADDR sp,
+- int struct_return, CORE_ADDR struct_addr)
+-{
+- /* NOTE: cagney/2004-02-27: This is a guess - its implemented by
+- reverse engineering testsuite failures. */
+-
+- /* Stack base address at which any pass-by-reference parameters are
+- stored. */
+- CORE_ADDR struct_end = 0;
+- /* Stack base address at which the first parameter is stored. */
+- CORE_ADDR param_end = 0;
+-
+- /* The inner most end of the stack after all the parameters have
+- been pushed. */
+- CORE_ADDR new_sp = 0;
+-
+- /* Two passes. First pass computes the location of everything,
+- second pass writes the bytes out. */
+- int write_pass;
+- for (write_pass = 0; write_pass < 2; write_pass++)
+- {
+- CORE_ADDR struct_ptr = 0;
+- CORE_ADDR param_ptr = 0;
+- int reg = 27; /* NOTE: Registers go down. */
+- int i;
+- for (i = 0; i < nargs; i++)
+- {
+- struct value *arg = args[i];
+- struct type *type = check_typedef (VALUE_TYPE (arg));
+- /* The corresponding parameter that is pushed onto the
+- stack, and [possibly] passed in a register. */
+- char param_val[8];
+- int param_len;
+- memset (param_val, 0, sizeof param_val);
+- if (TYPE_LENGTH (type) > 8)
+- {
+- /* Large parameter, pass by reference. Store the value
+- in "struct" area and then pass its address. */
+- param_len = 4;
+- struct_ptr += align_up (TYPE_LENGTH (type), 8);
+- if (write_pass)
+- write_memory (struct_end - struct_ptr, VALUE_CONTENTS (arg),
+- TYPE_LENGTH (type));
+- store_unsigned_integer (param_val, 4, struct_end - struct_ptr);
+- }
+- else if (TYPE_CODE (type) == TYPE_CODE_INT
+- || TYPE_CODE (type) == TYPE_CODE_ENUM)
+- {
+- /* Integer value store, right aligned. "unpack_long"
+- takes care of any sign-extension problems. */
+- param_len = align_up (TYPE_LENGTH (type), 4);
+- store_unsigned_integer (param_val, param_len,
+- unpack_long (type,
+- VALUE_CONTENTS (arg)));
+- }
+- else
+- {
+- /* Small struct value, store right aligned? */
+- param_len = align_up (TYPE_LENGTH (type), 4);
+- memcpy (param_val + param_len - TYPE_LENGTH (type),
+- VALUE_CONTENTS (arg), TYPE_LENGTH (type));
+- }
+- param_ptr += param_len;
+- reg -= param_len / 4;
+- if (write_pass)
+- {
+- write_memory (param_end - param_ptr, param_val, param_len);
+- if (reg >= 23)
+- {
+- regcache_cooked_write (regcache, reg, param_val);
+- if (param_len > 4)
+- regcache_cooked_write (regcache, reg + 1, param_val + 4);
+- }
+- }
+- }
+-
+- /* Update the various stack pointers. */
+- if (!write_pass)
+- {
+- struct_end = sp + struct_ptr;
+- /* PARAM_PTR already accounts for all the arguments passed
+- by the user. However, the ABI mandates minimum stack
+- space allocations for outgoing arguments. The ABI also
+- mandates minimum stack alignments which we must
+- preserve. */
+- param_end = struct_end + max (align_up (param_ptr, 8),
+- REG_PARM_STACK_SPACE);
+- }
+- }
+-
+- /* If a structure has to be returned, set up register 28 to hold its
+- address */
+- if (struct_return)
+- write_register (28, struct_addr);
+-
+- /* Set the return address. */
+- regcache_cooked_write_unsigned (regcache, RP_REGNUM, bp_addr);
+-
+- /* Update the Stack Pointer. */
+- regcache_cooked_write_unsigned (regcache, SP_REGNUM, param_end + 32);
+-
+- /* The stack will have 32 bytes of additional space for a frame marker. */
+- return param_end + 32;
+-}
+-
+-/* This function pushes a stack frame with arguments as part of the
+- inferior function calling mechanism.
+-
+- This is the version for the PA64, in which later arguments appear
+- at higher addresses. (The stack always grows towards higher
+- addresses.)
+-
+- We simply allocate the appropriate amount of stack space and put
+- arguments into their proper slots.
+-
+- This ABI also requires that the caller provide an argument pointer
+- to the callee, so we do that too. */
+-
+-CORE_ADDR
+-hppa64_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
+- struct regcache *regcache, CORE_ADDR bp_addr,
+- int nargs, struct value **args, CORE_ADDR sp,
+- int struct_return, CORE_ADDR struct_addr)
+-{
+- /* Array of arguments' offsets. */
+- int *offset = (int *) alloca (nargs * sizeof (int));
+-
+- /* Array of arguments' lengths: real lengths in bytes, not aligned
+- to word size. */
+- int *lengths = (int *) alloca (nargs * sizeof (int));
+-
+- /* The value of SP as it was passed into this function. */
+- CORE_ADDR orig_sp = sp;
+-
+- /* The number of stack bytes occupied by the current argument. */
+- int bytes_reserved;
+-
+- /* The total number of bytes reserved for the arguments. */
+- int cum_bytes_reserved = 0;
+-
+- /* Similarly, but aligned. */
+- int cum_bytes_aligned = 0;
+- int i;
+-
+- /* Iterate over each argument provided by the user. */
+- for (i = 0; i < nargs; i++)
+- {
+- struct type *arg_type = VALUE_TYPE (args[i]);
+-
+- /* Integral scalar values smaller than a register are padded on
+- the left. We do this by promoting them to full-width,
+- although the ABI says to pad them with garbage. */
+- if (is_integral_type (arg_type)
+- && TYPE_LENGTH (arg_type) < DEPRECATED_REGISTER_SIZE)
+- {
+- args[i] = value_cast ((TYPE_UNSIGNED (arg_type)
+- ? builtin_type_unsigned_long
+- : builtin_type_long),
+- args[i]);
+- arg_type = VALUE_TYPE (args[i]);
+- }
+-
+- lengths[i] = TYPE_LENGTH (arg_type);
+-
+- /* Align the size of the argument to the word size for this
+- target. */
+- bytes_reserved = (lengths[i] + DEPRECATED_REGISTER_SIZE - 1) & -DEPRECATED_REGISTER_SIZE;
+-
+- offset[i] = cum_bytes_reserved;
+-
+- /* Aggregates larger than eight bytes (the only types larger
+- than eight bytes we have) are aligned on a 16-byte boundary,
+- possibly padded on the right with garbage. This may leave an
+- empty word on the stack, and thus an unused register, as per
+- the ABI. */
+- if (bytes_reserved > 8)
+- {
+- /* Round up the offset to a multiple of two slots. */
+- int new_offset = ((offset[i] + 2*DEPRECATED_REGISTER_SIZE-1)
+- & -(2*DEPRECATED_REGISTER_SIZE));
+-
+- /* Note the space we've wasted, if any. */
+- bytes_reserved += new_offset - offset[i];
+- offset[i] = new_offset;
+- }
+-
+- cum_bytes_reserved += bytes_reserved;
+- }
+-
+- /* CUM_BYTES_RESERVED already accounts for all the arguments passed
+- by the user. However, the ABIs mandate minimum stack space
+- allocations for outgoing arguments.
+-
+- The ABIs also mandate minimum stack alignments which we must
+- preserve. */
+- cum_bytes_aligned = align_up (cum_bytes_reserved, 16);
+- sp += max (cum_bytes_aligned, REG_PARM_STACK_SPACE);
+-
+- /* Now write each of the args at the proper offset down the
+- stack. */
+- for (i = 0; i < nargs; i++)
+- write_memory (orig_sp + offset[i], VALUE_CONTENTS (args[i]), lengths[i]);
+-
+- /* If a structure has to be returned, set up register 28 to hold its
+- address */
+- if (struct_return)
+- write_register (28, struct_addr);
+-
+- /* For the PA64 we must pass a pointer to the outgoing argument
+- list. The ABI mandates that the pointer should point to the
+- first byte of storage beyond the register flushback area.
+-
+- However, the call dummy expects the outgoing argument pointer to
+- be passed in register %r4. */
+- write_register (4, orig_sp + REG_PARM_STACK_SPACE);
+-
+- /* ?!? This needs further work. We need to set up the global data
+- pointer for this procedure. This assumes the same global pointer
+- for every procedure. The call dummy expects the dp value to be
+- passed in register %r6. */
+- write_register (6, read_register (27));
+-
+- /* Set the return address. */
+- regcache_cooked_write_unsigned (regcache, RP_REGNUM, bp_addr);
+-
+- /* Update the Stack Pointer. */
+- regcache_cooked_write_unsigned (regcache, SP_REGNUM, sp + 64);
+-
+- /* The stack will have 64 bytes of additional space for a frame
+- marker. */
+- return sp + 64;
+-
+-}
+-
+-static CORE_ADDR
+-hppa32_frame_align (struct gdbarch *gdbarch, CORE_ADDR addr)
+-{
+- /* HP frames are 64-byte (or cache line) aligned (yes that's _byte_
+- and not _bit_)! */
+- return align_up (addr, 64);
+-}
+-
+-/* Force all frames to 16-byte alignment. Better safe than sorry. */
+-
+-static CORE_ADDR
+-hppa64_frame_align (struct gdbarch *gdbarch, CORE_ADDR addr)
+-{
+- /* Just always 16-byte align. */
+- return align_up (addr, 16);
+-}
+-
+-
+-/* elz: Used to lookup a symbol in the shared libraries.
+- This function calls shl_findsym, indirectly through a
+- call to __d_shl_get. __d_shl_get is in end.c, which is always
+- linked in by the hp compilers/linkers.
+- The call to shl_findsym cannot be made directly because it needs
+- to be active in target address space.
+- inputs: - minimal symbol pointer for the function we want to look up
+- - address in target space of the descriptor for the library
+- where we want to look the symbol up.
+- This address is retrieved using the
+- som_solib_get_solib_by_pc function (somsolib.c).
+- output: - real address in the library of the function.
+- note: the handle can be null, in which case shl_findsym will look for
+- the symbol in all the loaded shared libraries.
+- files to look at if you need reference on this stuff:
+- dld.c, dld_shl_findsym.c
+- end.c
+- man entry for shl_findsym */
+-
+-CORE_ADDR
+-find_stub_with_shl_get (struct minimal_symbol *function, CORE_ADDR handle)
+-{
+- struct symbol *get_sym, *symbol2;
+- struct minimal_symbol *buff_minsym, *msymbol;
+- struct type *ftype;
+- struct value **args;
+- struct value *funcval;
+- struct value *val;
+-
+- int x, namelen, err_value, tmp = -1;
+- CORE_ADDR endo_buff_addr, value_return_addr, errno_return_addr;
+- CORE_ADDR stub_addr;
+-
+-
+- args = alloca (sizeof (struct value *) * 8); /* 6 for the arguments and one null one??? */
+- funcval = find_function_in_inferior ("__d_shl_get");
+- get_sym = lookup_symbol ("__d_shl_get", NULL, VAR_DOMAIN, NULL, NULL);
+- buff_minsym = lookup_minimal_symbol ("__buffer", NULL, NULL);
+- msymbol = lookup_minimal_symbol ("__shldp", NULL, NULL);
+- symbol2 = lookup_symbol ("__shldp", NULL, VAR_DOMAIN, NULL, NULL);
+- endo_buff_addr = SYMBOL_VALUE_ADDRESS (buff_minsym);
+- namelen = strlen (DEPRECATED_SYMBOL_NAME (function));
+- value_return_addr = endo_buff_addr + namelen;
+- ftype = check_typedef (SYMBOL_TYPE (get_sym));
+-
+- /* do alignment */
+- if ((x = value_return_addr % 64) != 0)
+- value_return_addr = value_return_addr + 64 - x;
+-
+- errno_return_addr = value_return_addr + 64;
+-
+-
+- /* set up stuff needed by __d_shl_get in buffer in end.o */
+-
+- target_write_memory (endo_buff_addr, DEPRECATED_SYMBOL_NAME (function), namelen);
+-
+- target_write_memory (value_return_addr, (char *) &tmp, 4);
+-
+- target_write_memory (errno_return_addr, (char *) &tmp, 4);
+-
+- target_write_memory (SYMBOL_VALUE_ADDRESS (msymbol),
+- (char *) &handle, 4);
+-
+- /* now prepare the arguments for the call */
+-
+- args[0] = value_from_longest (TYPE_FIELD_TYPE (ftype, 0), 12);
+- args[1] = value_from_pointer (TYPE_FIELD_TYPE (ftype, 1), SYMBOL_VALUE_ADDRESS (msymbol));
+- args[2] = value_from_pointer (TYPE_FIELD_TYPE (ftype, 2), endo_buff_addr);
+- args[3] = value_from_longest (TYPE_FIELD_TYPE (ftype, 3), TYPE_PROCEDURE);
+- args[4] = value_from_pointer (TYPE_FIELD_TYPE (ftype, 4), value_return_addr);
+- args[5] = value_from_pointer (TYPE_FIELD_TYPE (ftype, 5), errno_return_addr);
+-
+- /* now call the function */
+-
+- val = call_function_by_hand (funcval, 6, args);
+-
+- /* now get the results */
+-
+- target_read_memory (errno_return_addr, (char *) &err_value, sizeof (err_value));
+-
+- target_read_memory (value_return_addr, (char *) &stub_addr, sizeof (stub_addr));
+- if (stub_addr <= 0)
+- error ("call to __d_shl_get failed, error code is %d", err_value);
+-
+- return (stub_addr);
+-}
+-
+-/* Cover routine for find_stub_with_shl_get to pass to catch_errors */
+-static int
+-cover_find_stub_with_shl_get (void *args_untyped)
+-{
+- args_for_find_stub *args = args_untyped;
+- args->return_val = find_stub_with_shl_get (args->msym, args->solib_handle);
+- return 0;
+-}
+-
+-/* Insert the specified number of args and function address
+- into a call sequence of the above form stored at DUMMYNAME.
+-
+- On the hppa we need to call the stack dummy through $$dyncall.
+- Therefore our version of DEPRECATED_FIX_CALL_DUMMY takes an extra
+- argument, real_pc, which is the location where gdb should start up
+- the inferior to do the function call.
+-
+- This has to work across several versions of hpux, bsd, osf1. It has to
+- work regardless of what compiler was used to build the inferior program.
+- It should work regardless of whether or not end.o is available. It has
+- to work even if gdb can not call into the dynamic loader in the inferior
+- to query it for symbol names and addresses.
+-
+- Yes, all those cases should work. Luckily code exists to handle most
+- of them. The complexity is in selecting exactly what scheme should
+- be used to perform the inferior call.
+-
+- At the current time this routine is known not to handle cases where
+- the program was linked with HP's compiler without including end.o.
+-
+- Please contact Jeff Law (law@cygnus.com) before changing this code. */
+-
+-CORE_ADDR
+-hppa_fix_call_dummy (char *dummy, CORE_ADDR pc, CORE_ADDR fun, int nargs,
+- struct value **args, struct type *type, int gcc_p)
+-{
+- CORE_ADDR dyncall_addr;
+- struct minimal_symbol *msymbol;
+- struct minimal_symbol *trampoline;
+- int flags = read_register (FLAGS_REGNUM);
+- struct unwind_table_entry *u = NULL;
+- CORE_ADDR new_stub = 0;
+- CORE_ADDR solib_handle = 0;
+-
+- /* Nonzero if we will use GCC's PLT call routine. This routine must be
+- passed an import stub, not a PLABEL. It is also necessary to set %r19
+- (the PIC register) before performing the call.
+-
+- If zero, then we are using __d_plt_call (HP's PLT call routine) or we
+- are calling the target directly. When using __d_plt_call we want to
+- use a PLABEL instead of an import stub. */
+- int using_gcc_plt_call = 1;
+-
+-#ifdef GDB_TARGET_IS_HPPA_20W
+- /* We currently use completely different code for the PA2.0W inferior
+- function call sequences. This needs to be cleaned up. */
+- {
+- CORE_ADDR pcsqh, pcsqt, pcoqh, pcoqt, sr5;
+- struct target_waitstatus w;
+- int inst1, inst2;
+- char buf[4];
+- int status;
+- struct objfile *objfile;
+-
+- /* We can not modify the PC space queues directly, so we start
+- up the inferior and execute a couple instructions to set the
+- space queues so that they point to the call dummy in the stack. */
+- pcsqh = read_register (PCSQ_HEAD_REGNUM);
+- sr5 = read_register (SR5_REGNUM);
+- if (1)
+- {
+- pcoqh = read_register (PCOQ_HEAD_REGNUM);
+- pcoqt = read_register (PCOQ_TAIL_REGNUM);
+- if (target_read_memory (pcoqh, buf, 4) != 0)
+- error ("Couldn't modify space queue\n");
+- inst1 = extract_unsigned_integer (buf, 4);
+-
+- if (target_read_memory (pcoqt, buf, 4) != 0)
+- error ("Couldn't modify space queue\n");
+- inst2 = extract_unsigned_integer (buf, 4);
+-
+- /* BVE (r1) */
+- *((int *) buf) = 0xe820d000;
+- if (target_write_memory (pcoqh, buf, 4) != 0)
+- error ("Couldn't modify space queue\n");
+-
+- /* NOP */
+- *((int *) buf) = 0x08000240;
+- if (target_write_memory (pcoqt, buf, 4) != 0)
+- {
+- *((int *) buf) = inst1;
+- target_write_memory (pcoqh, buf, 4);
+- error ("Couldn't modify space queue\n");
+- }
+-
+- write_register (1, pc);
+-
+- /* Single step twice, the BVE instruction will set the space queue
+- such that it points to the PC value written immediately above
+- (ie the call dummy). */
+- resume (1, 0);
+- target_wait (inferior_ptid, &w);
+- resume (1, 0);
+- target_wait (inferior_ptid, &w);
+-
+- /* Restore the two instructions at the old PC locations. */
+- *((int *) buf) = inst1;
+- target_write_memory (pcoqh, buf, 4);
+- *((int *) buf) = inst2;
+- target_write_memory (pcoqt, buf, 4);
+- }
+-
+- /* The call dummy wants the ultimate destination address initially
+- in register %r5. */
+- write_register (5, fun);
+-
+- /* We need to see if this objfile has a different DP value than our
+- own (it could be a shared library for example). */
+- ALL_OBJFILES (objfile)
+- {
+- struct obj_section *s;
+- obj_private_data_t *obj_private;
+-
+- /* See if FUN is in any section within this shared library. */
+- for (s = objfile->sections; s < objfile->sections_end; s++)
+- if (s->addr <= fun && fun < s->endaddr)
+- break;
+-
+- if (s >= objfile->sections_end)
+- continue;
+-
+- obj_private = (obj_private_data_t *) objfile->obj_private;
+-
+- /* The DP value may be different for each objfile. But within an
+- objfile each function uses the same dp value. Thus we do not need
+- to grope around the opd section looking for dp values.
+-
+- ?!? This is not strictly correct since we may be in a shared library
+- and want to call back into the main program. To make that case
+- work correctly we need to set obj_private->dp for the main program's
+- objfile, then remove this conditional. */
+- if (obj_private->dp)
+- write_register (27, obj_private->dp);
+- break;
+- }
+- return pc;
+- }
+-#endif
+-
+-#ifndef GDB_TARGET_IS_HPPA_20W
+- /* Prefer __gcc_plt_call over the HP supplied routine because
+- __gcc_plt_call works for any number of arguments. */
+- trampoline = NULL;
+- if (lookup_minimal_symbol ("__gcc_plt_call", NULL, NULL) == NULL)
+- using_gcc_plt_call = 0;
+-
+- msymbol = lookup_minimal_symbol ("$$dyncall", NULL, NULL);
+- if (msymbol == NULL)
+- error ("Can't find an address for $$dyncall trampoline");
+-
+- dyncall_addr = SYMBOL_VALUE_ADDRESS (msymbol);
+-
+- /* FUN could be a procedure label, in which case we have to get
+- its real address and the value of its GOT/DP if we plan to
+- call the routine via gcc_plt_call. */
+- if ((fun & 0x2) && using_gcc_plt_call)
+- {
+- /* Get the GOT/DP value for the target function. It's
+- at *(fun+4). Note the call dummy is *NOT* allowed to
+- trash %r19 before calling the target function. */
+- write_register (19, read_memory_integer ((fun & ~0x3) + 4,
+- DEPRECATED_REGISTER_SIZE));
+-
+- /* Now get the real address for the function we are calling, it's
+- at *fun. */
+- fun = (CORE_ADDR) read_memory_integer (fun & ~0x3,
+- TARGET_PTR_BIT / 8);
+- }
+- else
+- {
+-
+-#ifndef GDB_TARGET_IS_PA_ELF
+- /* FUN could be an export stub, the real address of a function, or
+- a PLABEL. When using gcc's PLT call routine we must call an import
+- stub rather than the export stub or real function for lazy binding
+- to work correctly
+-
+- If we are using the gcc PLT call routine, then we need to
+- get the import stub for the target function. */
+- if (using_gcc_plt_call && som_solib_get_got_by_pc (fun))
+- {
+- struct objfile *objfile;
+- struct minimal_symbol *funsymbol, *stub_symbol;
+- CORE_ADDR newfun = 0;
+-
+- funsymbol = lookup_minimal_symbol_by_pc (fun);
+- if (!funsymbol)
+- error ("Unable to find minimal symbol for target function.\n");
+-
+- /* Search all the object files for an import symbol with the
+- right name. */
+- ALL_OBJFILES (objfile)
+- {
+- stub_symbol
+- = lookup_minimal_symbol_solib_trampoline
+- (DEPRECATED_SYMBOL_NAME (funsymbol), objfile);
+-
+- if (!stub_symbol)
+- stub_symbol = lookup_minimal_symbol (DEPRECATED_SYMBOL_NAME (funsymbol),
+- NULL, objfile);
+-
+- /* Found a symbol with the right name. */
+- if (stub_symbol)
+- {
+- struct unwind_table_entry *u;
+- /* It must be a shared library trampoline. */
+- if (MSYMBOL_TYPE (stub_symbol) != mst_solib_trampoline)
+- continue;
+-
+- /* It must also be an import stub. */
+- u = find_unwind_entry (SYMBOL_VALUE (stub_symbol));
+- if (u == NULL
+- || (u->stub_unwind.stub_type != IMPORT
+-#ifdef GDB_NATIVE_HPUX_11
+- /* Sigh. The hpux 10.20 dynamic linker will blow
+- chunks if we perform a call to an unbound function
+- via the IMPORT_SHLIB stub. The hpux 11.00 dynamic
+- linker will blow chunks if we do not call the
+- unbound function via the IMPORT_SHLIB stub.
+-
+- We currently have no way to select bevahior on just
+- the target. However, we only support HPUX/SOM in
+- native mode. So we conditinalize on a native
+- #ifdef. Ugly. Ugly. Ugly */
+- && u->stub_unwind.stub_type != IMPORT_SHLIB
+-#endif
+- ))
+- continue;
+-
+- /* OK. Looks like the correct import stub. */
+- newfun = SYMBOL_VALUE (stub_symbol);
+- fun = newfun;
+-
+- /* If we found an IMPORT stub, then we want to stop
+- searching now. If we found an IMPORT_SHLIB, we want
+- to continue the search in the hopes that we will find
+- an IMPORT stub. */
+- if (u->stub_unwind.stub_type == IMPORT)
+- break;
+- }
+- }
+-
+- /* Ouch. We did not find an import stub. Make an attempt to
+- do the right thing instead of just croaking. Most of the
+- time this will actually work. */
+- if (newfun == 0)
+- write_register (19, som_solib_get_got_by_pc (fun));
+-
+- u = find_unwind_entry (fun);
+- if (u
+- && (u->stub_unwind.stub_type == IMPORT
+- || u->stub_unwind.stub_type == IMPORT_SHLIB))
+- trampoline = lookup_minimal_symbol ("__gcc_plt_call", NULL, NULL);
+-
+- /* If we found the import stub in the shared library, then we have
+- to set %r19 before we call the stub. */
+- if (u && u->stub_unwind.stub_type == IMPORT_SHLIB)
+- write_register (19, som_solib_get_got_by_pc (fun));
+- }
+-#endif
+- }
+-
+- /* If we are calling into another load module then have sr4export call the
+- magic __d_plt_call routine which is linked in from end.o.
+-
+- You can't use _sr4export to make the call as the value in sp-24 will get
+- fried and you end up returning to the wrong location. You can't call the
+- target as the code to bind the PLT entry to a function can't return to a
+- stack address.
+-
+- Also, query the dynamic linker in the inferior to provide a suitable
+- PLABEL for the target function. */
+- if (!using_gcc_plt_call)
+- {
+- CORE_ADDR new_fun;
+-
+- /* Get a handle for the shared library containing FUN. Given the
+- handle we can query the shared library for a PLABEL. */
+- solib_handle = som_solib_get_solib_by_pc (fun);
+-
+- if (solib_handle)
+- {
+- struct minimal_symbol *fmsymbol = lookup_minimal_symbol_by_pc (fun);
+-
+- trampoline = lookup_minimal_symbol ("__d_plt_call", NULL, NULL);
+-
+- if (trampoline == NULL)
+- {
+- error ("Can't find an address for __d_plt_call or __gcc_plt_call trampoline\nSuggest linking executable with -g or compiling with gcc.");
+- }
+-
+- /* This is where sr4export will jump to. */
+- new_fun = SYMBOL_VALUE_ADDRESS (trampoline);
+-
+- /* If the function is in a shared library, then call __d_shl_get to
+- get a PLABEL for the target function. */
+- new_stub = find_stub_with_shl_get (fmsymbol, solib_handle);
+-
+- if (new_stub == 0)
+- error ("Can't find an import stub for %s", DEPRECATED_SYMBOL_NAME (fmsymbol));
+-
+- /* We have to store the address of the stub in __shlib_funcptr. */
+- msymbol = lookup_minimal_symbol ("__shlib_funcptr", NULL,
+- (struct objfile *) NULL);
+-
+- if (msymbol == NULL)
+- error ("Can't find an address for __shlib_funcptr");
+- target_write_memory (SYMBOL_VALUE_ADDRESS (msymbol),
+- (char *) &new_stub, 4);
+-
+- /* We want sr4export to call __d_plt_call, so we claim it is
+- the final target. Clear trampoline. */
+- fun = new_fun;
+- trampoline = NULL;
+- }
+- }
+-
+- /* Store upper 21 bits of function address into ldil. fun will either be
+- the final target (most cases) or __d_plt_call when calling into a shared
+- library and __gcc_plt_call is not available. */
+- store_unsigned_integer
+- (&dummy[FUNC_LDIL_OFFSET],
+- INSTRUCTION_SIZE,
+- deposit_21 (fun >> 11,
+- extract_unsigned_integer (&dummy[FUNC_LDIL_OFFSET],
+- INSTRUCTION_SIZE)));
+-
+- /* Store lower 11 bits of function address into ldo */
+- store_unsigned_integer
+- (&dummy[FUNC_LDO_OFFSET],
+- INSTRUCTION_SIZE,
+- deposit_14 (fun & MASK_11,
+- extract_unsigned_integer (&dummy[FUNC_LDO_OFFSET],
+- INSTRUCTION_SIZE)));
+-#ifdef SR4EXPORT_LDIL_OFFSET
+-
+- {
+- CORE_ADDR trampoline_addr;
+-
+- /* We may still need sr4export's address too. */
+-
+- if (trampoline == NULL)
+- {
+- msymbol = lookup_minimal_symbol ("_sr4export", NULL, NULL);
+- if (msymbol == NULL)
+- error ("Can't find an address for _sr4export trampoline");
+-
+- trampoline_addr = SYMBOL_VALUE_ADDRESS (msymbol);
+- }
+- else
+- trampoline_addr = SYMBOL_VALUE_ADDRESS (trampoline);
+-
+-
+- /* Store upper 21 bits of trampoline's address into ldil */
+- store_unsigned_integer
+- (&dummy[SR4EXPORT_LDIL_OFFSET],
+- INSTRUCTION_SIZE,
+- deposit_21 (trampoline_addr >> 11,
+- extract_unsigned_integer (&dummy[SR4EXPORT_LDIL_OFFSET],
+- INSTRUCTION_SIZE)));
+-
+- /* Store lower 11 bits of trampoline's address into ldo */
+- store_unsigned_integer
+- (&dummy[SR4EXPORT_LDO_OFFSET],
+- INSTRUCTION_SIZE,
+- deposit_14 (trampoline_addr & MASK_11,
+- extract_unsigned_integer (&dummy[SR4EXPORT_LDO_OFFSET],
+- INSTRUCTION_SIZE)));
+- }
+-#endif
+-
+- write_register (22, pc);
+-
+- /* 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.
+-
+- Similarly if the current PC is in a shared library. Note however,
+- this scheme won't work if the shared library isn't mapped into
+- the same space as the stack. */
+- if (flags & 2)
+- return pc;
+-#ifndef GDB_TARGET_IS_PA_ELF
+- else if (som_solib_get_got_by_pc (hppa_target_read_pc (inferior_ptid)))
+- return pc;
+-#endif
+- else
+- return dyncall_addr;
+-#endif
+-}
+-
+-/* If the pid is in a syscall, then the FP register is not readable.
+- We'll return zero in that case, rather than attempting to read it
+- and cause a warning. */
+-
+-CORE_ADDR
+-hppa_read_fp (int pid)
+-{
+- int flags = read_register (FLAGS_REGNUM);
+-
+- if (flags & 2)
+- {
+- return (CORE_ADDR) 0;
+- }
+-
+- /* This is the only site that may directly read_register () the FP
+- register. All others must use deprecated_read_fp (). */
+- return read_register (DEPRECATED_FP_REGNUM);
+-}
+-
+-CORE_ADDR
+-hppa_target_read_fp (void)
+-{
+- return hppa_read_fp (PIDGET (inferior_ptid));
+-}
+-
+-/* Get the PC from %r31 if currently in a syscall. Also mask out privilege
+- bits. */
+-
+-CORE_ADDR
+-hppa_target_read_pc (ptid_t ptid)
+-{
+- int flags = read_register_pid (FLAGS_REGNUM, ptid);
+-
+- /* The following test does not belong here. It is OS-specific, and belongs
+- in native code. */
+- /* Test SS_INSYSCALL */
+- if (flags & 2)
+- return read_register_pid (31, ptid) & ~0x3;
+-
+- return read_register_pid (PC_REGNUM, ptid) & ~0x3;
+-}
+-
+-/* Write out the PC. If currently in a syscall, then also write the new
+- PC value into %r31. */
+-
+-void
+-hppa_target_write_pc (CORE_ADDR v, ptid_t ptid)
+-{
+- int flags = read_register_pid (FLAGS_REGNUM, ptid);
+-
+- /* The following test does not belong here. It is OS-specific, and belongs
+- in native code. */
+- /* If in a syscall, then set %r31. Also make sure to get the
+- privilege bits set correctly. */
+- /* Test SS_INSYSCALL */
+- if (flags & 2)
+- write_register_pid (31, v | 0x3, ptid);
+-
+- write_register_pid (PC_REGNUM, v, ptid);
+- write_register_pid (PCOQ_TAIL_REGNUM, v + 4, ptid);
+-}
+-
+-/* return the alignment of a type in bytes. Structures have the maximum
+- alignment required by their fields. */
+-
+-static int
+-hppa_alignof (struct type *type)
+-{
+- int max_align, align, i;
+- CHECK_TYPEDEF (type);
+- switch (TYPE_CODE (type))
+- {
+- case TYPE_CODE_PTR:
+- case TYPE_CODE_INT:
+- case TYPE_CODE_FLT:
+- return TYPE_LENGTH (type);
+- case TYPE_CODE_ARRAY:
+- return hppa_alignof (TYPE_FIELD_TYPE (type, 0));
+- case TYPE_CODE_STRUCT:
+- case TYPE_CODE_UNION:
+- max_align = 1;
+- for (i = 0; i < TYPE_NFIELDS (type); i++)
+- {
+- /* Bit fields have no real alignment. */
+- /* if (!TYPE_FIELD_BITPOS (type, i)) */
+- if (!TYPE_FIELD_BITSIZE (type, i)) /* elz: this should be bitsize */
+- {
+- align = hppa_alignof (TYPE_FIELD_TYPE (type, i));
+- max_align = max (max_align, align);
+- }
+- }
+- return max_align;
+- default:
+- return 4;
+- }
+-}
+-
+-/* Print the register regnum, or all registers if regnum is -1 */
+-
+-void
+-pa_do_registers_info (int regnum, int fpregs)
+-{
+- char *raw_regs = alloca (DEPRECATED_REGISTER_BYTES);
+- int i;
+-
+- /* Make a copy of gdb's save area (may cause actual
+- reads from the target). */
+- for (i = 0; i < NUM_REGS; i++)
+- frame_register_read (deprecated_selected_frame, i,
+- raw_regs + DEPRECATED_REGISTER_BYTE (i));
+-
+- if (regnum == -1)
+- pa_print_registers (raw_regs, regnum, fpregs);
+- else if (regnum < FP4_REGNUM)
+- {
+- long reg_val[2];
+-
+- /* Why is the value not passed through "extract_signed_integer"
+- as in "pa_print_registers" below? */
+- pa_register_look_aside (raw_regs, regnum, &reg_val[0]);
+-
+- if (!is_pa_2)
+- {
+- printf_unfiltered ("%s %lx\n", REGISTER_NAME (regnum), reg_val[1]);
+- }
+- else
+- {
+- /* Fancy % formats to prevent leading zeros. */
+- if (reg_val[0] == 0)
+- printf_unfiltered ("%s %lx\n", REGISTER_NAME (regnum), reg_val[1]);
+- else
+- printf_unfiltered ("%s %lx%8.8lx\n", REGISTER_NAME (regnum),
+- reg_val[0], reg_val[1]);
+- }
+- }
+- else
+- /* Note that real floating point values only start at
+- FP4_REGNUM. FP0 and up are just status and error
+- registers, which have integral (bit) values. */
+- pa_print_fp_reg (regnum);
+-}
+-
+-/********** new function ********************/
+-void
+-pa_do_strcat_registers_info (int regnum, int fpregs, struct ui_file *stream,
+- enum precision_type precision)
+-{
+- char *raw_regs = alloca (DEPRECATED_REGISTER_BYTES);
+- int i;
+-
+- /* Make a copy of gdb's save area (may cause actual
+- reads from the target). */
+- for (i = 0; i < NUM_REGS; i++)
+- frame_register_read (deprecated_selected_frame, i,
+- raw_regs + DEPRECATED_REGISTER_BYTE (i));
+-
+- if (regnum == -1)
+- pa_strcat_registers (raw_regs, regnum, fpregs, stream);
+-
+- else if (regnum < FP4_REGNUM)
+- {
+- long reg_val[2];
+-
+- /* Why is the value not passed through "extract_signed_integer"
+- as in "pa_print_registers" below? */
+- pa_register_look_aside (raw_regs, regnum, &reg_val[0]);
+-
+- if (!is_pa_2)
+- {
+- fprintf_unfiltered (stream, "%s %lx", REGISTER_NAME (regnum), reg_val[1]);
+- }
+- else
+- {
+- /* Fancy % formats to prevent leading zeros. */
+- if (reg_val[0] == 0)
+- fprintf_unfiltered (stream, "%s %lx", REGISTER_NAME (regnum),
+- reg_val[1]);
+- else
+- fprintf_unfiltered (stream, "%s %lx%8.8lx", REGISTER_NAME (regnum),
+- reg_val[0], reg_val[1]);
+- }
+- }
+- else
+- /* Note that real floating point values only start at
+- FP4_REGNUM. FP0 and up are just status and error
+- registers, which have integral (bit) values. */
+- pa_strcat_fp_reg (regnum, stream, precision);
+-}
+-
+-/* If this is a PA2.0 machine, fetch the real 64-bit register
+- value. Otherwise use the info from gdb's saved register area.
+-
+- Note that reg_val is really expected to be an array of longs,
+- with two elements. */
+-static void
+-pa_register_look_aside (char *raw_regs, int regnum, long *raw_val)
+-{
+- static int know_which = 0; /* False */
+-
+- int regaddr;
+- unsigned int offset;
+- int i;
+- int start;
+-
+-
+- char buf[MAX_REGISTER_SIZE];
+- long long reg_val;
+-
+- if (!know_which)
+- {
+- if (CPU_PA_RISC2_0 == sysconf (_SC_CPU_VERSION))
+- {
+- is_pa_2 = (1 == 1);
+- }
+-
+- know_which = 1; /* True */
+- }
+-
+- raw_val[0] = 0;
+- raw_val[1] = 0;
+-
+- if (!is_pa_2)
+- {
+- raw_val[1] = *(long *) (raw_regs + DEPRECATED_REGISTER_BYTE (regnum));
+- return;
+- }
+-
+- /* Code below copied from hppah-nat.c, with fixes for wide
+- registers, using different area of save_state, etc. */
+- if (regnum == FLAGS_REGNUM || regnum >= FP0_REGNUM ||
+- !HAVE_STRUCT_SAVE_STATE_T || !HAVE_STRUCT_MEMBER_SS_WIDE)
+- {
+- /* Use narrow regs area of save_state and default macro. */
+- offset = U_REGS_OFFSET;
+- regaddr = register_addr (regnum, offset);
+- start = 1;
+- }
+- else
+- {
+- /* Use wide regs area, and calculate registers as 8 bytes wide.
+-
+- We'd like to do this, but current version of "C" doesn't
+- permit "offsetof":
+-
+- offset = offsetof(save_state_t, ss_wide);
+-
+- Note that to avoid "C" doing typed pointer arithmetic, we
+- have to cast away the type in our offset calculation:
+- otherwise we get an offset of 1! */
+-
+- /* NB: save_state_t is not available before HPUX 9.
+- The ss_wide field is not available previous to HPUX 10.20,
+- so to avoid compile-time warnings, we only compile this for
+- PA 2.0 processors. This control path should only be followed
+- if we're debugging a PA 2.0 processor, so this should not cause
+- problems. */
+-
+- /* #if the following code out so that this file can still be
+- compiled on older HPUX boxes (< 10.20) which don't have
+- this structure/structure member. */
+-#if HAVE_STRUCT_SAVE_STATE_T == 1 && HAVE_STRUCT_MEMBER_SS_WIDE == 1
+- save_state_t temp;
+-
+- offset = ((int) &temp.ss_wide) - ((int) &temp);
+- regaddr = offset + regnum * 8;
+- start = 0;
+-#endif
+- }
+-
+- for (i = start; i < 2; i++)
+- {
+- errno = 0;
+- raw_val[i] = call_ptrace (PT_RUREGS, PIDGET (inferior_ptid),
+- (PTRACE_ARG3_TYPE) regaddr, 0);
+- if (errno != 0)
+- {
+- /* Warning, not error, in case we are attached; sometimes the
+- kernel doesn't let us at the registers. */
+- char *err = safe_strerror (errno);
+- char *msg = alloca (strlen (err) + 128);
+- sprintf (msg, "reading register %s: %s", REGISTER_NAME (regnum), err);
+- warning (msg);
+- goto error_exit;
+- }
+-
+- regaddr += sizeof (long);
+- }
+-
+- if (regnum == PCOQ_HEAD_REGNUM || regnum == PCOQ_TAIL_REGNUM)
+- raw_val[1] &= ~0x3; /* I think we're masking out space bits */
+-
+-error_exit:
+- ;
+-}
+-
+-/* "Info all-reg" command */
+-
+-static void
+-pa_print_registers (char *raw_regs, int regnum, int fpregs)
+-{
+- int i, j;
+- /* Alas, we are compiled so that "long long" is 32 bits */
+- long raw_val[2];
+- long long_val;
+- int rows = 48, columns = 2;
+-
+- for (i = 0; i < rows; i++)
+- {
+- for (j = 0; j < columns; j++)
+- {
+- /* We display registers in column-major order. */
+- int regnum = i + j * rows;
+-
+- /* Q: Why is the value passed through "extract_signed_integer",
+- while above, in "pa_do_registers_info" it isn't?
+- A: ? */
+- pa_register_look_aside (raw_regs, regnum, &raw_val[0]);
+-
+- /* Even fancier % formats to prevent leading zeros
+- and still maintain the output in columns. */
+- if (!is_pa_2)
+- {
+- /* Being big-endian, on this machine the low bits
+- (the ones we want to look at) are in the second longword. */
+- long_val = extract_signed_integer (&raw_val[1], 4);
+- printf_filtered ("%10.10s: %8lx ",
+- REGISTER_NAME (regnum), long_val);
+- }
+- else
+- {
+- /* raw_val = extract_signed_integer(&raw_val, 8); */
+- if (raw_val[0] == 0)
+- printf_filtered ("%10.10s: %8lx ",
+- REGISTER_NAME (regnum), raw_val[1]);
+- else
+- printf_filtered ("%10.10s: %8lx%8.8lx ",
+- REGISTER_NAME (regnum),
+- raw_val[0], raw_val[1]);
+- }
+- }
+- printf_unfiltered ("\n");
+- }
+-
+- if (fpregs)
+- for (i = FP4_REGNUM; i < NUM_REGS; i++) /* FP4_REGNUM == 72 */
+- pa_print_fp_reg (i);
++ /* The stack will have 32 bytes of additional space for a frame marker. */
++ return param_end + 64;
+ }
+
+-/************* new function ******************/
+-static void
+-pa_strcat_registers (char *raw_regs, int regnum, int fpregs,
+- struct ui_file *stream)
++static CORE_ADDR
++hppa32_frame_align (struct gdbarch *gdbarch, CORE_ADDR addr)
+ {
+- int i, j;
+- long raw_val[2]; /* Alas, we are compiled so that "long long" is 32 bits */
+- long long_val;
+- enum precision_type precision;
+-
+- precision = unspecified_precision;
+-
+- for (i = 0; i < 18; i++)
+- {
+- for (j = 0; j < 4; j++)
+- {
+- /* Q: Why is the value passed through "extract_signed_integer",
+- while above, in "pa_do_registers_info" it isn't?
+- A: ? */
+- pa_register_look_aside (raw_regs, i + (j * 18), &raw_val[0]);
+-
+- /* Even fancier % formats to prevent leading zeros
+- and still maintain the output in columns. */
+- if (!is_pa_2)
+- {
+- /* Being big-endian, on this machine the low bits
+- (the ones we want to look at) are in the second longword. */
+- long_val = extract_signed_integer (&raw_val[1], 4);
+- fprintf_filtered (stream, "%8.8s: %8lx ",
+- REGISTER_NAME (i + (j * 18)), long_val);
+- }
+- else
+- {
+- /* raw_val = extract_signed_integer(&raw_val, 8); */
+- if (raw_val[0] == 0)
+- fprintf_filtered (stream, "%8.8s: %8lx ",
+- REGISTER_NAME (i + (j * 18)), raw_val[1]);
+- else
+- fprintf_filtered (stream, "%8.8s: %8lx%8.8lx ",
+- REGISTER_NAME (i + (j * 18)), raw_val[0],
+- raw_val[1]);
+- }
+- }
+- fprintf_unfiltered (stream, "\n");
+- }
+-
+- if (fpregs)
+- for (i = FP4_REGNUM; i < NUM_REGS; i++) /* FP4_REGNUM == 72 */
+- pa_strcat_fp_reg (i, stream, precision);
++ /* HP frames are 64-byte (or cache line) aligned (yes that's _byte_
++ and not _bit_)! */
++ return align_up (addr, 64);
+ }
+
+-static void
+-pa_print_fp_reg (int i)
+-{
+- char raw_buffer[MAX_REGISTER_SIZE];
+- char virtual_buffer[MAX_REGISTER_SIZE];
+-
+- /* Get 32bits of data. */
+- frame_register_read (deprecated_selected_frame, i, raw_buffer);
+-
+- /* Put it in the buffer. No conversions are ever necessary. */
+- memcpy (virtual_buffer, raw_buffer, DEPRECATED_REGISTER_RAW_SIZE (i));
+-
+- fputs_filtered (REGISTER_NAME (i), gdb_stdout);
+- print_spaces_filtered (8 - strlen (REGISTER_NAME (i)), gdb_stdout);
+- fputs_filtered ("(single precision) ", gdb_stdout);
++/* Force all frames to 16-byte alignment. Better safe than sorry. */
+
+- val_print (DEPRECATED_REGISTER_VIRTUAL_TYPE (i), virtual_buffer, 0, 0, gdb_stdout, 0,
+- 1, 0, Val_pretty_default);
+- printf_filtered ("\n");
++static CORE_ADDR
++hppa64_frame_align (struct gdbarch *gdbarch, CORE_ADDR addr)
++{
++ /* Just always 16-byte align. */
++ return align_up (addr, 16);
++}
+
+- /* If "i" is even, then this register can also be a double-precision
+- FP register. Dump it out as such. */
+- if ((i % 2) == 0)
+- {
+- /* Get the data in raw format for the 2nd half. */
+- frame_register_read (deprecated_selected_frame, i + 1, raw_buffer);
+
+- /* Copy it into the appropriate part of the virtual buffer. */
+- memcpy (virtual_buffer + DEPRECATED_REGISTER_RAW_SIZE (i), raw_buffer,
+- DEPRECATED_REGISTER_RAW_SIZE (i));
+-
+- /* Dump it as a double. */
+- fputs_filtered (REGISTER_NAME (i), gdb_stdout);
+- print_spaces_filtered (8 - strlen (REGISTER_NAME (i)), gdb_stdout);
+- fputs_filtered ("(double precision) ", gdb_stdout);
+-
+- val_print (builtin_type_double, virtual_buffer, 0, 0, gdb_stdout, 0,
+- 1, 0, Val_pretty_default);
+- printf_filtered ("\n");
+- }
+-}
++/* Get the PC from %r31 if currently in a syscall. Also mask out privilege
++ bits. */
+
+-/*************** new function ***********************/
+-static void
+-pa_strcat_fp_reg (int i, struct ui_file *stream, enum precision_type precision)
++CORE_ADDR
++hppa_target_read_pc (ptid_t ptid)
+ {
+- char raw_buffer[MAX_REGISTER_SIZE];
+- char virtual_buffer[MAX_REGISTER_SIZE];
+-
+- fputs_filtered (REGISTER_NAME (i), stream);
+- print_spaces_filtered (8 - strlen (REGISTER_NAME (i)), stream);
++ int flags = read_register_pid (FLAGS_REGNUM, ptid);
+
+- /* Get 32bits of data. */
+- frame_register_read (deprecated_selected_frame, i, raw_buffer);
++ /* The following test does not belong here. It is OS-specific, and belongs
++ in native code. */
++ /* Test SS_INSYSCALL */
++ if (flags & 2)
++ return read_register_pid (31, ptid) & ~0x3;
+
+- /* Put it in the buffer. No conversions are ever necessary. */
+- memcpy (virtual_buffer, raw_buffer, DEPRECATED_REGISTER_RAW_SIZE (i));
++ return read_register_pid (PCOQ_HEAD_REGNUM, ptid) & ~0x3;
++}
+
+- if (precision == double_precision && (i % 2) == 0)
+- {
++/* Write out the PC. If currently in a syscall, then also write the new
++ PC value into %r31. */
+
+- char raw_buf[MAX_REGISTER_SIZE];
++void
++hppa_target_write_pc (CORE_ADDR v, ptid_t ptid)
++{
++ int flags = read_register_pid (FLAGS_REGNUM, ptid);
+
+- /* Get the data in raw format for the 2nd half. */
+- frame_register_read (deprecated_selected_frame, i + 1, raw_buf);
++ /* The following test does not belong here. It is OS-specific, and belongs
++ in native code. */
++ /* If in a syscall, then set %r31. Also make sure to get the
++ privilege bits set correctly. */
++ /* Test SS_INSYSCALL */
++ if (flags & 2)
++ write_register_pid (31, v | 0x3, ptid);
+
+- /* Copy it into the appropriate part of the virtual buffer. */
+- memcpy (virtual_buffer + DEPRECATED_REGISTER_RAW_SIZE (i), raw_buf,
+- DEPRECATED_REGISTER_RAW_SIZE (i));
++ write_register_pid (PCOQ_HEAD_REGNUM, v, ptid);
++ write_register_pid (PCOQ_TAIL_REGNUM, v + 4, ptid);
++}
+
+- val_print (builtin_type_double, virtual_buffer, 0, 0, stream, 0,
+- 1, 0, Val_pretty_default);
++/* return the alignment of a type in bytes. Structures have the maximum
++ alignment required by their fields. */
+
+- }
+- else
++static int
++hppa_alignof (struct type *type)
++{
++ int max_align, align, i;
++ CHECK_TYPEDEF (type);
++ switch (TYPE_CODE (type))
+ {
+- val_print (DEPRECATED_REGISTER_VIRTUAL_TYPE (i), virtual_buffer, 0, 0, stream, 0,
+- 1, 0, Val_pretty_default);
++ case TYPE_CODE_PTR:
++ case TYPE_CODE_INT:
++ case TYPE_CODE_FLT:
++ return TYPE_LENGTH (type);
++ case TYPE_CODE_ARRAY:
++ return hppa_alignof (TYPE_FIELD_TYPE (type, 0));
++ case TYPE_CODE_STRUCT:
++ case TYPE_CODE_UNION:
++ max_align = 1;
++ for (i = 0; i < TYPE_NFIELDS (type); i++)
++ {
++ /* Bit fields have no real alignment. */
++ /* if (!TYPE_FIELD_BITPOS (type, i)) */
++ if (!TYPE_FIELD_BITSIZE (type, i)) /* elz: this should be bitsize */
++ {
++ align = hppa_alignof (TYPE_FIELD_TYPE (type, i));
++ max_align = max (max_align, align);
++ }
++ }
++ return max_align;
++ default:
++ return 4;
+ }
+-
+ }
+
+ /* Return one if PC is in the call path of a trampoline, else return zero.
+@@ -3867,7 +1585,7 @@
+ rp from sp - 8. */
+ if (prev_inst == 0x4bc23ff1)
+ return (read_memory_integer
+- (read_register (SP_REGNUM) - 8, 4)) & ~0x3;
++ (read_register (HPPA_SP_REGNUM) - 8, 4)) & ~0x3;
+ else
+ {
+ warning ("Unable to find restore of %%rp before bv (%%rp).");
+@@ -3881,7 +1599,7 @@
+ else if ((curr_inst & 0xffe0f000) == 0xe840d000)
+ {
+ return (read_memory_integer
+- (read_register (SP_REGNUM) - 24, TARGET_PTR_BIT / 8)) & ~0x3;
++ (read_register (HPPA_SP_REGNUM) - 24, TARGET_PTR_BIT / 8)) & ~0x3;
+ }
+
+ /* What about be,n 0(sr0,%rp)? It's just another way we return to
+@@ -3893,7 +1611,7 @@
+ I guess we could check for the previous instruction being
+ mtsp %r1,%sr0 if we want to do sanity checking. */
+ return (read_memory_integer
+- (read_register (SP_REGNUM) - 24, TARGET_PTR_BIT / 8)) & ~0x3;
++ (read_register (HPPA_SP_REGNUM) - 24, TARGET_PTR_BIT / 8)) & ~0x3;
+ }
+
+ /* Haven't found the branch yet, but we're still in the stub.
+@@ -4080,7 +1798,7 @@
+ for (i = 3; i < u->Entry_GR + 3; i++)
+ {
+ /* Frame pointer gets saved into a special location. */
+- if (u->Save_SP && i == DEPRECATED_FP_REGNUM)
++ if (u->Save_SP && i == HPPA_FP_REGNUM)
+ continue;
+
+ save_gr |= (1 << i);
+@@ -4267,334 +1985,78 @@
+ goto restart;
+ }
+
+- return pc;
+-}
+-
+-
+-/* Return the address of the PC after the last prologue instruction if
+- we can determine it from the debug symbols. Else return zero. */
+-
+-static CORE_ADDR
+-after_prologue (CORE_ADDR pc)
+-{
+- struct symtab_and_line sal;
+- CORE_ADDR func_addr, func_end;
+- struct symbol *f;
+-
+- /* If we can not find the symbol in the partial symbol table, then
+- there is no hope we can determine the function's start address
+- with this code. */
+- if (!find_pc_partial_function (pc, NULL, &func_addr, &func_end))
+- return 0;
+-
+- /* Get the line associated with FUNC_ADDR. */
+- sal = find_pc_line (func_addr, 0);
+-
+- /* There are only two cases to consider. First, the end of the source line
+- is within the function bounds. In that case we return the end of the
+- source line. Second is the end of the source line extends beyond the
+- bounds of the current function. We need to use the slow code to
+- examine instructions in that case.
+-
+- Anything else is simply a bug elsewhere. Fixing it here is absolutely
+- the wrong thing to do. In fact, it should be entirely possible for this
+- function to always return zero since the slow instruction scanning code
+- is supposed to *always* work. If it does not, then it is a bug. */
+- if (sal.end < func_end)
+- return sal.end;
+- else
+- return 0;
+-}
+-
+-/* To skip prologues, I use this predicate. Returns either PC itself
+- if the code at PC does not look like a function prologue; otherwise
+- returns an address that (if we're lucky) follows the prologue. If
+- LENIENT, then we must skip everything which is involved in setting
+- up the frame (it's OK to skip more, just so long as we don't skip
+- anything which might clobber the registers which are being saved.
+- Currently we must not skip more on the alpha, but we might the lenient
+- stuff some day. */
+-
+-CORE_ADDR
+-hppa_skip_prologue (CORE_ADDR pc)
+-{
+- unsigned long inst;
+- int offset;
+- CORE_ADDR post_prologue_pc;
+- char buf[4];
+-
+- /* See if we can determine the end of the prologue via the symbol table.
+- If so, then return either PC, or the PC after the prologue, whichever
+- is greater. */
+-
+- post_prologue_pc = after_prologue (pc);
+-
+- /* If after_prologue returned a useful address, then use it. Else
+- fall back on the instruction skipping code.
+-
+- Some folks have claimed this causes problems because the breakpoint
+- may be the first instruction of the prologue. If that happens, then
+- the instruction skipping code has a bug that needs to be fixed. */
+- if (post_prologue_pc != 0)
+- return max (pc, post_prologue_pc);
+- else
+- return (skip_prologue_hard_way (pc));
+-}
+-
+-/* Put here the code to store, into the SAVED_REGS, the addresses of
+- the saved registers of frame described by FRAME_INFO. This
+- includes special registers such as pc and fp saved in special ways
+- in the stack frame. sp is even more special: the address we return
+- for it IS the sp for the next frame. */
+-
+-void
+-hppa_frame_find_saved_regs (struct frame_info *frame_info,
+- CORE_ADDR frame_saved_regs[])
+-{
+- CORE_ADDR pc;
+- struct unwind_table_entry *u;
+- unsigned long inst, stack_remaining, save_gr, save_fr, save_rp, save_sp;
+- int status, i, reg;
+- char buf[4];
+- int fp_loc = -1;
+- int final_iteration;
+-
+- /* Zero out everything. */
+- memset (frame_saved_regs, '\0', SIZEOF_FRAME_SAVED_REGS);
+-
+- /* Call dummy frames always look the same, so there's no need to
+- examine the dummy code to determine locations of saved registers;
+- instead, let find_dummy_frame_regs fill in the correct offsets
+- for the saved registers. */
+- if ((get_frame_pc (frame_info) >= get_frame_base (frame_info)
+- && (get_frame_pc (frame_info)
+- <= (get_frame_base (frame_info)
+- /* A call dummy is sized in words, but it is actually a
+- series of instructions. Account for that scaling
+- factor. */
+- + ((DEPRECATED_REGISTER_SIZE / INSTRUCTION_SIZE)
+- * DEPRECATED_CALL_DUMMY_LENGTH)
+- /* Similarly we have to account for 64bit wide register
+- saves. */
+- + (32 * DEPRECATED_REGISTER_SIZE)
+- /* We always consider FP regs 8 bytes long. */
+- + (NUM_REGS - FP0_REGNUM) * 8
+- /* Similarly we have to account for 64bit wide register
+- saves. */
+- + (6 * DEPRECATED_REGISTER_SIZE)))))
+- find_dummy_frame_regs (frame_info, frame_saved_regs);
+-
+- /* Interrupt handlers are special too. They lay out the register
+- state in the exact same order as the register numbers in GDB. */
+- if (pc_in_interrupt_handler (get_frame_pc (frame_info)))
+- {
+- for (i = 0; i < NUM_REGS; i++)
+- {
+- /* SP is a little special. */
+- if (i == SP_REGNUM)
+- frame_saved_regs[SP_REGNUM]
+- = read_memory_integer (get_frame_base (frame_info) + SP_REGNUM * 4,
+- TARGET_PTR_BIT / 8);
+- else
+- frame_saved_regs[i] = get_frame_base (frame_info) + i * 4;
+- }
+- return;
+- }
+-
+-#ifdef FRAME_FIND_SAVED_REGS_IN_SIGTRAMP
+- /* Handle signal handler callers. */
+- if ((get_frame_type (frame_info) == SIGTRAMP_FRAME))
+- {
+- FRAME_FIND_SAVED_REGS_IN_SIGTRAMP (frame_info, frame_saved_regs);
+- return;
+- }
+-#endif
+-
+- /* Get the starting address of the function referred to by the PC
+- saved in frame. */
+- pc = get_frame_func (frame_info);
+-
+- /* Yow! */
+- u = find_unwind_entry (pc);
+- if (!u)
+- return;
+-
+- /* This is how much of a frame adjustment we need to account for. */
+- stack_remaining = u->Total_frame_size << 3;
+-
+- /* Magic register saves we want to know about. */
+- save_rp = u->Save_RP;
+- save_sp = u->Save_SP;
+-
+- /* Turn the Entry_GR field into a bitmask. */
+- save_gr = 0;
+- for (i = 3; i < u->Entry_GR + 3; i++)
+- {
+- /* Frame pointer gets saved into a special location. */
+- if (u->Save_SP && i == DEPRECATED_FP_REGNUM)
+- continue;
+-
+- save_gr |= (1 << i);
+- }
+-
+- /* Turn the Entry_FR field into a bitmask too. */
+- save_fr = 0;
+- for (i = 12; i < u->Entry_FR + 12; i++)
+- save_fr |= (1 << i);
+-
+- /* The frame always represents the value of %sp at entry to the
+- current function (and is thus equivalent to the "saved" stack
+- pointer. */
+- frame_saved_regs[SP_REGNUM] = get_frame_base (frame_info);
+-
+- /* Loop until we find everything of interest or hit a branch.
+-
+- For unoptimized GCC code and for any HP CC code this will never ever
+- examine any user instructions.
+-
+- For optimized GCC code we're faced with problems. GCC will schedule
+- its prologue and make prologue instructions available for delay slot
+- filling. The end result is user code gets mixed in with the prologue
+- and a prologue instruction may be in the delay slot of the first branch
+- or call.
+-
+- Some unexpected things are expected with debugging optimized code, so
+- we allow this routine to walk past user instructions in optimized
+- GCC code. */
+- final_iteration = 0;
+- while ((save_gr || save_fr || save_rp || save_sp || stack_remaining > 0)
+- && pc <= get_frame_pc (frame_info))
+- {
+- status = target_read_memory (pc, buf, 4);
+- inst = extract_unsigned_integer (buf, 4);
+-
+- /* Yow! */
+- if (status != 0)
+- return;
+-
+- /* Note the interesting effects of this instruction. */
+- stack_remaining -= prologue_inst_adjust_sp (inst);
+-
+- /* There are limited ways to store the return pointer into the
+- stack. */
+- if (inst == 0x6bc23fd9) /* stw rp,-0x14(sr0,sp) */
+- {
+- save_rp = 0;
+- frame_saved_regs[RP_REGNUM] = get_frame_base (frame_info) - 20;
+- }
+- else if (inst == 0x0fc212c1) /* std rp,-0x10(sr0,sp) */
+- {
+- save_rp = 0;
+- frame_saved_regs[RP_REGNUM] = get_frame_base (frame_info) - 16;
+- }
+-
+- /* Note if we saved SP into the stack. This also happens to indicate
+- the location of the saved frame pointer. */
+- if ( (inst & 0xffffc000) == 0x6fc10000 /* stw,ma r1,N(sr0,sp) */
+- || (inst & 0xffffc00c) == 0x73c10008) /* std,ma r1,N(sr0,sp) */
+- {
+- frame_saved_regs[DEPRECATED_FP_REGNUM] = get_frame_base (frame_info);
+- save_sp = 0;
+- }
+-
+- /* Account for general and floating-point register saves. */
+- reg = inst_saves_gr (inst);
+- if (reg >= 3 && reg <= 18
+- && (!u->Save_SP || reg != DEPRECATED_FP_REGNUM))
+- {
+- save_gr &= ~(1 << reg);
++ return pc;
++}
+
+- /* stwm with a positive displacement is a *post modify*. */
+- if ((inst >> 26) == 0x1b
+- && extract_14 (inst) >= 0)
+- frame_saved_regs[reg] = get_frame_base (frame_info);
+- /* A std has explicit post_modify forms. */
+- else if ((inst & 0xfc00000c) == 0x70000008)
+- frame_saved_regs[reg] = get_frame_base (frame_info);
+- else
+- {
+- CORE_ADDR offset;
+
+- if ((inst >> 26) == 0x1c)
+- offset = (inst & 0x1 ? -1 << 13 : 0) | (((inst >> 4) & 0x3ff) << 3);
+- else if ((inst >> 26) == 0x03)
+- offset = low_sign_extend (inst & 0x1f, 5);
+- else
+- offset = extract_14 (inst);
++/* Return the address of the PC after the last prologue instruction if
++ we can determine it from the debug symbols. Else return zero. */
+
+- /* Handle code with and without frame pointers. */
+- if (u->Save_SP)
+- frame_saved_regs[reg]
+- = get_frame_base (frame_info) + offset;
+- else
+- frame_saved_regs[reg]
+- = (get_frame_base (frame_info) + (u->Total_frame_size << 3)
+- + offset);
+- }
+- }
++static CORE_ADDR
++after_prologue (CORE_ADDR pc)
++{
++ struct symtab_and_line sal;
++ CORE_ADDR func_addr, func_end;
++ struct symbol *f;
+
++ /* If we can not find the symbol in the partial symbol table, then
++ there is no hope we can determine the function's start address
++ with this code. */
++ if (!find_pc_partial_function (pc, NULL, &func_addr, &func_end))
++ return 0;
+
+- /* GCC handles callee saved FP regs a little differently.
++ /* Get the line associated with FUNC_ADDR. */
++ sal = find_pc_line (func_addr, 0);
+
+- It emits an instruction to put the value of the start of
+- the FP store area into %r1. It then uses fstds,ma with
+- a basereg of %r1 for the stores.
+-
+- HP CC emits them at the current stack pointer modifying
+- the stack pointer as it stores each register. */
+-
+- /* ldo X(%r3),%r1 or ldo X(%r30),%r1. */
+- if ((inst & 0xffffc000) == 0x34610000
+- || (inst & 0xffffc000) == 0x37c10000)
+- fp_loc = extract_14 (inst);
++ /* There are only two cases to consider. First, the end of the source line
++ is within the function bounds. In that case we return the end of the
++ source line. Second is the end of the source line extends beyond the
++ bounds of the current function. We need to use the slow code to
++ examine instructions in that case.
+
+- reg = inst_saves_fr (inst);
+- if (reg >= 12 && reg <= 21)
+- {
+- /* Note +4 braindamage below is necessary because the FP status
+- registers are internally 8 registers rather than the expected
+- 4 registers. */
+- save_fr &= ~(1 << reg);
+- if (fp_loc == -1)
+- {
+- /* 1st HP CC FP register store. After this instruction
+- we've set enough state that the GCC and HPCC code are
+- both handled in the same manner. */
+- frame_saved_regs[reg + FP4_REGNUM + 4] = get_frame_base (frame_info);
+- fp_loc = 8;
+- }
+- else
+- {
+- frame_saved_regs[reg + FP0_REGNUM + 4]
+- = get_frame_base (frame_info) + fp_loc;
+- fp_loc += 8;
+- }
+- }
++ Anything else is simply a bug elsewhere. Fixing it here is absolutely
++ the wrong thing to do. In fact, it should be entirely possible for this
++ function to always return zero since the slow instruction scanning code
++ is supposed to *always* work. If it does not, then it is a bug. */
++ if (sal.end < func_end)
++ return sal.end;
++ else
++ return 0;
++}
+
+- /* Quit if we hit any kind of branch the previous iteration. */
+- if (final_iteration)
+- break;
++/* To skip prologues, I use this predicate. Returns either PC itself
++ if the code at PC does not look like a function prologue; otherwise
++ returns an address that (if we're lucky) follows the prologue. If
++ LENIENT, then we must skip everything which is involved in setting
++ up the frame (it's OK to skip more, just so long as we don't skip
++ anything which might clobber the registers which are being saved.
++ Currently we must not skip more on the alpha, but we might the lenient
++ stuff some day. */
+
+- /* We want to look precisely one instruction beyond the branch
+- if we have not found everything yet. */
+- if (is_branch (inst))
+- final_iteration = 1;
++CORE_ADDR
++hppa_skip_prologue (CORE_ADDR pc)
++{
++ unsigned long inst;
++ int offset;
++ CORE_ADDR post_prologue_pc;
++ char buf[4];
+
+- /* Bump the PC. */
+- pc += 4;
+- }
+-}
++ /* See if we can determine the end of the prologue via the symbol table.
++ If so, then return either PC, or the PC after the prologue, whichever
++ is greater. */
+
+-/* XXX - deprecated. This is a compatibility function for targets
+- that do not yet implement DEPRECATED_FRAME_INIT_SAVED_REGS. */
+-/* Find the addresses in which registers are saved in FRAME. */
++ post_prologue_pc = after_prologue (pc);
+
+-static void
+-hppa_frame_init_saved_regs (struct frame_info *frame)
+-{
+- if (deprecated_get_frame_saved_regs (frame) == NULL)
+- frame_saved_regs_zalloc (frame);
+- hppa_frame_find_saved_regs (frame, deprecated_get_frame_saved_regs (frame));
++ /* If after_prologue returned a useful address, then use it. Else
++ fall back on the instruction skipping code.
++
++ Some folks have claimed this causes problems because the breakpoint
++ may be the first instruction of the prologue. If that happens, then
++ the instruction skipping code has a bug that needs to be fixed. */
++ if (post_prologue_pc != 0)
++ return max (pc, post_prologue_pc);
++ else
++ return (skip_prologue_hard_way (pc));
+ }
+
+ struct hppa_frame_cache
+@@ -4630,7 +2092,7 @@
+ for (i = 3; i < u->Entry_GR + 3; i++)
+ {
+ /* Frame pointer gets saved into a special location. */
+- if (u->Save_SP && i == DEPRECATED_FP_REGNUM)
++ if (u->Save_SP && i == HPPA_FP_REGNUM)
+ continue;
+
+ saved_gr_mask |= (1 << i);
+@@ -4700,13 +2162,13 @@
+ || (inst & 0xffffc00c) == 0x73c10008) /* std,ma r1,N(sr0,sp) */
+ {
+ looking_for_sp = 0;
+- cache->saved_regs[DEPRECATED_FP_REGNUM].addr = 0;
++ cache->saved_regs[HPPA_FP_REGNUM].addr = 0;
+ }
+
+ /* Account for general and floating-point register saves. */
+ reg = inst_saves_gr (inst);
+ if (reg >= 3 && reg <= 18
+- && (!u->Save_SP || reg != DEPRECATED_FP_REGNUM))
++ && (!u->Save_SP || reg != HPPA_FP_REGNUM))
+ {
+ saved_gr_mask &= ~(1 << reg);
+ if ((inst >> 26) == 0x1b && extract_14 (inst) >= 0)
+@@ -4766,7 +2228,7 @@
+ }
+ else
+ {
+- cache->saved_regs[reg + FP0_REGNUM + 4].addr = fp_loc;
++ cache->saved_regs[reg + HPPA_FP0_REGNUM + 4].addr = fp_loc;
+ fp_loc += 8;
+ }
+ }
+@@ -4785,10 +2247,10 @@
+ /* The frame base always represents the value of %sp at entry to
+ the current function (and is thus equivalent to the "saved"
+ stack pointer. */
+- CORE_ADDR this_sp = frame_unwind_register_unsigned (next_frame, SP_REGNUM);
++ CORE_ADDR this_sp = frame_unwind_register_unsigned (next_frame, HPPA_SP_REGNUM);
+ /* FIXME: cagney/2004-02-22: This assumes that the frame has been
+ created. If it hasn't everything will be out-of-wack. */
+- if (u->Save_SP && trad_frame_addr_p (cache->saved_regs, SP_REGNUM))
++ if (u->Save_SP && trad_frame_addr_p (cache->saved_regs, HPPA_SP_REGNUM))
+ /* Both we're expecting the SP to be saved and the SP has been
+ saved. The entry SP value is saved at this frame's SP
+ address. */
+@@ -4797,7 +2259,7 @@
+ /* The prologue has been slowly allocating stack space. Adjust
+ the SP back. */
+ cache->base = this_sp - frame_size;
+- trad_frame_set_value (cache->saved_regs, SP_REGNUM, cache->base);
++ trad_frame_set_value (cache->saved_regs, HPPA_SP_REGNUM, cache->base);
+ }
+
+ /* The PC is found in the "return register", "Millicode" uses "r31"
+@@ -4907,468 +2369,14 @@
+ hppa_unwind_dummy_id (struct gdbarch *gdbarch, struct frame_info *next_frame)
+ {
+ return frame_id_build (frame_unwind_register_unsigned (next_frame,
+- SP_REGNUM),
++ HPPA_SP_REGNUM),
+ frame_pc_unwind (next_frame));
+ }
+
+ static CORE_ADDR
+ hppa_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
+ {
+- return frame_unwind_register_signed (next_frame, PC_REGNUM) & ~3;
+-}
+-
+-/* Exception handling support for the HP-UX ANSI C++ compiler.
+- The compiler (aCC) provides a callback for exception events;
+- GDB can set a breakpoint on this callback and find out what
+- exception event has occurred. */
+-
+-/* The name of the hook to be set to point to the callback function */
+-static char HP_ACC_EH_notify_hook[] = "__eh_notify_hook";
+-/* The name of the function to be used to set the hook value */
+-static char HP_ACC_EH_set_hook_value[] = "__eh_set_hook_value";
+-/* The name of the callback function in end.o */
+-static char HP_ACC_EH_notify_callback[] = "__d_eh_notify_callback";
+-/* Name of function in end.o on which a break is set (called by above) */
+-static char HP_ACC_EH_break[] = "__d_eh_break";
+-/* Name of flag (in end.o) that enables catching throws */
+-static char HP_ACC_EH_catch_throw[] = "__d_eh_catch_throw";
+-/* Name of flag (in end.o) that enables catching catching */
+-static char HP_ACC_EH_catch_catch[] = "__d_eh_catch_catch";
+-/* The enum used by aCC */
+-typedef enum
+- {
+- __EH_NOTIFY_THROW,
+- __EH_NOTIFY_CATCH
+- }
+-__eh_notification;
+-
+-/* Is exception-handling support available with this executable? */
+-static int hp_cxx_exception_support = 0;
+-/* Has the initialize function been run? */
+-int hp_cxx_exception_support_initialized = 0;
+-/* Similar to above, but imported from breakpoint.c -- non-target-specific */
+-extern int exception_support_initialized;
+-/* Address of __eh_notify_hook */
+-static CORE_ADDR eh_notify_hook_addr = 0;
+-/* Address of __d_eh_notify_callback */
+-static CORE_ADDR eh_notify_callback_addr = 0;
+-/* Address of __d_eh_break */
+-static CORE_ADDR eh_break_addr = 0;
+-/* Address of __d_eh_catch_catch */
+-static CORE_ADDR eh_catch_catch_addr = 0;
+-/* Address of __d_eh_catch_throw */
+-static CORE_ADDR eh_catch_throw_addr = 0;
+-/* Sal for __d_eh_break */
+-static struct symtab_and_line *break_callback_sal = 0;
+-
+-/* Code in end.c expects __d_pid to be set in the inferior,
+- otherwise __d_eh_notify_callback doesn't bother to call
+- __d_eh_break! So we poke the pid into this symbol
+- ourselves.
+- 0 => success
+- 1 => failure */
+-int
+-setup_d_pid_in_inferior (void)
+-{
+- CORE_ADDR anaddr;
+- struct minimal_symbol *msymbol;
+- char buf[4]; /* FIXME 32x64? */
+-
+- /* Slam the pid of the process into __d_pid; failing is only a warning! */
+- msymbol = lookup_minimal_symbol ("__d_pid", NULL, symfile_objfile);
+- if (msymbol == NULL)
+- {
+- warning ("Unable to find __d_pid symbol in object file.");
+- warning ("Suggest linking executable with -g (links in /opt/langtools/lib/end.o).");
+- return 1;
+- }
+-
+- anaddr = SYMBOL_VALUE_ADDRESS (msymbol);
+- store_unsigned_integer (buf, 4, PIDGET (inferior_ptid)); /* FIXME 32x64? */
+- if (target_write_memory (anaddr, buf, 4)) /* FIXME 32x64? */
+- {
+- warning ("Unable to write __d_pid");
+- warning ("Suggest linking executable with -g (links in /opt/langtools/lib/end.o).");
+- return 1;
+- }
+- return 0;
+-}
+-
+-/* Initialize exception catchpoint support by looking for the
+- necessary hooks/callbacks in end.o, etc., and set the hook value to
+- point to the required debug function
+-
+- Return 0 => failure
+- 1 => success */
+-
+-static int
+-initialize_hp_cxx_exception_support (void)
+-{
+- struct symtabs_and_lines sals;
+- struct cleanup *old_chain;
+- struct cleanup *canonical_strings_chain = NULL;
+- int i;
+- char *addr_start;
+- char *addr_end = NULL;
+- char **canonical = (char **) NULL;
+- int thread = -1;
+- struct symbol *sym = NULL;
+- struct minimal_symbol *msym = NULL;
+- struct objfile *objfile;
+- asection *shlib_info;
+-
+- /* Detect and disallow recursion. On HP-UX with aCC, infinite
+- recursion is a possibility because finding the hook for exception
+- callbacks involves making a call in the inferior, which means
+- re-inserting breakpoints which can re-invoke this code */
+-
+- static int recurse = 0;
+- if (recurse > 0)
+- {
+- hp_cxx_exception_support_initialized = 0;
+- exception_support_initialized = 0;
+- return 0;
+- }
+-
+- hp_cxx_exception_support = 0;
+-
+- /* First check if we have seen any HP compiled objects; if not,
+- it is very unlikely that HP's idiosyncratic callback mechanism
+- for exception handling debug support will be available!
+- This will percolate back up to breakpoint.c, where our callers
+- will decide to try the g++ exception-handling support instead. */
+- if (!hp_som_som_object_present)
+- return 0;
+-
+- /* We have a SOM executable with SOM debug info; find the hooks */
+-
+- /* First look for the notify hook provided by aCC runtime libs */
+- /* If we find this symbol, we conclude that the executable must
+- have HP aCC exception support built in. If this symbol is not
+- found, even though we're a HP SOM-SOM file, we may have been
+- built with some other compiler (not aCC). This results percolates
+- back up to our callers in breakpoint.c which can decide to
+- try the g++ style of exception support instead.
+- If this symbol is found but the other symbols we require are
+- not found, there is something weird going on, and g++ support
+- should *not* be tried as an alternative.
+-
+- ASSUMPTION: Only HP aCC code will have __eh_notify_hook defined.
+- ASSUMPTION: HP aCC and g++ modules cannot be linked together. */
+-
+- /* libCsup has this hook; it'll usually be non-debuggable */
+- msym = lookup_minimal_symbol (HP_ACC_EH_notify_hook, NULL, NULL);
+- if (msym)
+- {
+- eh_notify_hook_addr = SYMBOL_VALUE_ADDRESS (msym);
+- hp_cxx_exception_support = 1;
+- }
+- else
+- {
+- warning ("Unable to find exception callback hook (%s).", HP_ACC_EH_notify_hook);
+- warning ("Executable may not have been compiled debuggable with HP aCC.");
+- warning ("GDB will be unable to intercept exception events.");
+- eh_notify_hook_addr = 0;
+- hp_cxx_exception_support = 0;
+- return 0;
+- }
+-
+- /* Next look for the notify callback routine in end.o */
+- /* This is always available in the SOM symbol dictionary if end.o is linked in */
+- msym = lookup_minimal_symbol (HP_ACC_EH_notify_callback, NULL, NULL);
+- if (msym)
+- {
+- eh_notify_callback_addr = SYMBOL_VALUE_ADDRESS (msym);
+- hp_cxx_exception_support = 1;
+- }
+- else
+- {
+- warning ("Unable to find exception callback routine (%s).", HP_ACC_EH_notify_callback);
+- warning ("Suggest linking executable with -g (links in /opt/langtools/lib/end.o).");
+- warning ("GDB will be unable to intercept exception events.");
+- eh_notify_callback_addr = 0;
+- return 0;
+- }
+-
+-#ifndef GDB_TARGET_IS_HPPA_20W
+- /* Check whether the executable is dynamically linked or archive bound */
+- /* With an archive-bound executable we can use the raw addresses we find
+- for the callback function, etc. without modification. For an executable
+- with shared libraries, we have to do more work to find the plabel, which
+- can be the target of a call through $$dyncall from the aCC runtime support
+- library (libCsup) which is linked shared by default by aCC. */
+- /* This test below was copied from somsolib.c/somread.c. It may not be a very
+- reliable one to test that an executable is linked shared. pai/1997-07-18 */
+- shlib_info = bfd_get_section_by_name (symfile_objfile->obfd, "$SHLIB_INFO$");
+- if (shlib_info && (bfd_section_size (symfile_objfile->obfd, shlib_info) != 0))
+- {
+- /* The minsym we have has the local code address, but that's not the
+- plabel that can be used by an inter-load-module call. */
+- /* Find solib handle for main image (which has end.o), and use that
+- and the min sym as arguments to __d_shl_get() (which does the equivalent
+- of shl_findsym()) to find the plabel. */
+-
+- args_for_find_stub args;
+- static char message[] = "Error while finding exception callback hook:\n";
+-
+- args.solib_handle = som_solib_get_solib_by_pc (eh_notify_callback_addr);
+- args.msym = msym;
+- args.return_val = 0;
+-
+- recurse++;
+- catch_errors (cover_find_stub_with_shl_get, &args, message,
+- RETURN_MASK_ALL);
+- eh_notify_callback_addr = args.return_val;
+- recurse--;
+-
+- exception_catchpoints_are_fragile = 1;
+-
+- if (!eh_notify_callback_addr)
+- {
+- /* We can get here either if there is no plabel in the export list
+- for the main image, or if something strange happened (?) */
+- warning ("Couldn't find a plabel (indirect function label) for the exception callback.");
+- warning ("GDB will not be able to intercept exception events.");
+- return 0;
+- }
+- }
+- else
+- exception_catchpoints_are_fragile = 0;
+-#endif
+-
+- /* Now, look for the breakpointable routine in end.o */
+- /* This should also be available in the SOM symbol dict. if end.o linked in */
+- msym = lookup_minimal_symbol (HP_ACC_EH_break, NULL, NULL);
+- if (msym)
+- {
+- eh_break_addr = SYMBOL_VALUE_ADDRESS (msym);
+- hp_cxx_exception_support = 1;
+- }
+- else
+- {
+- warning ("Unable to find exception callback routine to set breakpoint (%s).", HP_ACC_EH_break);
+- warning ("Suggest linking executable with -g (link in /opt/langtools/lib/end.o).");
+- warning ("GDB will be unable to intercept exception events.");
+- eh_break_addr = 0;
+- return 0;
+- }
+-
+- /* Next look for the catch enable flag provided in end.o */
+- sym = lookup_symbol (HP_ACC_EH_catch_catch, (struct block *) NULL,
+- VAR_DOMAIN, 0, (struct symtab **) NULL);
+- if (sym) /* sometimes present in debug info */
+- {
+- eh_catch_catch_addr = SYMBOL_VALUE_ADDRESS (sym);
+- hp_cxx_exception_support = 1;
+- }
+- else
+- /* otherwise look in SOM symbol dict. */
+- {
+- msym = lookup_minimal_symbol (HP_ACC_EH_catch_catch, NULL, NULL);
+- if (msym)
+- {
+- eh_catch_catch_addr = SYMBOL_VALUE_ADDRESS (msym);
+- hp_cxx_exception_support = 1;
+- }
+- else
+- {
+- warning ("Unable to enable interception of exception catches.");
+- warning ("Executable may not have been compiled debuggable with HP aCC.");
+- warning ("Suggest linking executable with -g (link in /opt/langtools/lib/end.o).");
+- return 0;
+- }
+- }
+-
+- /* Next look for the catch enable flag provided end.o */
+- sym = lookup_symbol (HP_ACC_EH_catch_catch, (struct block *) NULL,
+- VAR_DOMAIN, 0, (struct symtab **) NULL);
+- if (sym) /* sometimes present in debug info */
+- {
+- eh_catch_throw_addr = SYMBOL_VALUE_ADDRESS (sym);
+- hp_cxx_exception_support = 1;
+- }
+- else
+- /* otherwise look in SOM symbol dict. */
+- {
+- msym = lookup_minimal_symbol (HP_ACC_EH_catch_throw, NULL, NULL);
+- if (msym)
+- {
+- eh_catch_throw_addr = SYMBOL_VALUE_ADDRESS (msym);
+- hp_cxx_exception_support = 1;
+- }
+- else
+- {
+- warning ("Unable to enable interception of exception throws.");
+- warning ("Executable may not have been compiled debuggable with HP aCC.");
+- warning ("Suggest linking executable with -g (link in /opt/langtools/lib/end.o).");
+- return 0;
+- }
+- }
+-
+- /* Set the flags */
+- hp_cxx_exception_support = 2; /* everything worked so far */
+- hp_cxx_exception_support_initialized = 1;
+- exception_support_initialized = 1;
+-
+- return 1;
+-}
+-
+-/* Target operation for enabling or disabling interception of
+- exception events.
+- KIND is either EX_EVENT_THROW or EX_EVENT_CATCH
+- ENABLE is either 0 (disable) or 1 (enable).
+- Return value is NULL if no support found;
+- -1 if something went wrong,
+- or a pointer to a symtab/line struct if the breakpointable
+- address was found. */
+-
+-struct symtab_and_line *
+-child_enable_exception_callback (enum exception_event_kind kind, int enable)
+-{
+- char buf[4];
+-
+- if (!exception_support_initialized || !hp_cxx_exception_support_initialized)
+- if (!initialize_hp_cxx_exception_support ())
+- return NULL;
+-
+- switch (hp_cxx_exception_support)
+- {
+- case 0:
+- /* Assuming no HP support at all */
+- return NULL;
+- case 1:
+- /* HP support should be present, but something went wrong */
+- return (struct symtab_and_line *) -1; /* yuck! */
+- /* there may be other cases in the future */
+- }
+-
+- /* Set the EH hook to point to the callback routine */
+- store_unsigned_integer (buf, 4, enable ? eh_notify_callback_addr : 0); /* FIXME 32x64 problem */
+- /* pai: (temp) FIXME should there be a pack operation first? */
+- if (target_write_memory (eh_notify_hook_addr, buf, 4)) /* FIXME 32x64 problem */
+- {
+- warning ("Could not write to target memory for exception event callback.");
+- warning ("Interception of exception events may not work.");
+- return (struct symtab_and_line *) -1;
+- }
+- if (enable)
+- {
+- /* Ensure that __d_pid is set up correctly -- end.c code checks this. :-( */
+- if (PIDGET (inferior_ptid) > 0)
+- {
+- if (setup_d_pid_in_inferior ())
+- return (struct symtab_and_line *) -1;
+- }
+- else
+- {
+- warning ("Internal error: Invalid inferior pid? Cannot intercept exception events.");
+- return (struct symtab_and_line *) -1;
+- }
+- }
+-
+- switch (kind)
+- {
+- case EX_EVENT_THROW:
+- store_unsigned_integer (buf, 4, enable ? 1 : 0);
+- if (target_write_memory (eh_catch_throw_addr, buf, 4)) /* FIXME 32x64? */
+- {
+- warning ("Couldn't enable exception throw interception.");
+- return (struct symtab_and_line *) -1;
+- }
+- break;
+- case EX_EVENT_CATCH:
+- store_unsigned_integer (buf, 4, enable ? 1 : 0);
+- if (target_write_memory (eh_catch_catch_addr, buf, 4)) /* FIXME 32x64? */
+- {
+- warning ("Couldn't enable exception catch interception.");
+- return (struct symtab_and_line *) -1;
+- }
+- break;
+- default:
+- error ("Request to enable unknown or unsupported exception event.");
+- }
+-
+- /* Copy break address into new sal struct, malloc'ing if needed. */
+- if (!break_callback_sal)
+- {
+- break_callback_sal = (struct symtab_and_line *) xmalloc (sizeof (struct symtab_and_line));
+- }
+- init_sal (break_callback_sal);
+- break_callback_sal->symtab = NULL;
+- break_callback_sal->pc = eh_break_addr;
+- break_callback_sal->line = 0;
+- break_callback_sal->end = eh_break_addr;
+-
+- return break_callback_sal;
+-}
+-
+-/* Record some information about the current exception event */
+-static struct exception_event_record current_ex_event;
+-/* Convenience struct */
+-static struct symtab_and_line null_symtab_and_line =
+-{NULL, 0, 0, 0};
+-
+-/* Report current exception event. Returns a pointer to a record
+- that describes the kind of the event, where it was thrown from,
+- and where it will be caught. More information may be reported
+- in the future */
+-struct exception_event_record *
+-child_get_current_exception_event (void)
+-{
+- CORE_ADDR event_kind;
+- CORE_ADDR throw_addr;
+- CORE_ADDR catch_addr;
+- struct frame_info *fi, *curr_frame;
+- int level = 1;
+-
+- curr_frame = get_current_frame ();
+- if (!curr_frame)
+- return (struct exception_event_record *) NULL;
+-
+- /* Go up one frame to __d_eh_notify_callback, because at the
+- point when this code is executed, there's garbage in the
+- arguments of __d_eh_break. */
+- fi = find_relative_frame (curr_frame, &level);
+- if (level != 0)
+- return (struct exception_event_record *) NULL;
+-
+- select_frame (fi);
+-
+- /* Read in the arguments */
+- /* __d_eh_notify_callback() is called with 3 arguments:
+- 1. event kind catch or throw
+- 2. the target address if known
+- 3. a flag -- not sure what this is. pai/1997-07-17 */
+- event_kind = read_register (ARG0_REGNUM);
+- catch_addr = read_register (ARG1_REGNUM);
+-
+- /* Now go down to a user frame */
+- /* For a throw, __d_eh_break is called by
+- __d_eh_notify_callback which is called by
+- __notify_throw which is called
+- from user code.
+- For a catch, __d_eh_break is called by
+- __d_eh_notify_callback which is called by
+- <stackwalking stuff> which is called by
+- __throw__<stuff> or __rethrow_<stuff> which is called
+- from user code. */
+- /* FIXME: Don't use such magic numbers; search for the frames */
+- level = (event_kind == EX_EVENT_THROW) ? 3 : 4;
+- fi = find_relative_frame (curr_frame, &level);
+- if (level != 0)
+- return (struct exception_event_record *) NULL;
+-
+- select_frame (fi);
+- throw_addr = get_frame_pc (fi);
+-
+- /* Go back to original (top) frame */
+- select_frame (curr_frame);
+-
+- current_ex_event.kind = (enum exception_event_kind) event_kind;
+- current_ex_event.throw_sal = find_pc_line (throw_addr, 1);
+- current_ex_event.catch_sal = find_pc_line (catch_addr, 1);
+-
+- return &current_ex_event;
++ return frame_unwind_register_signed (next_frame, PCOQ_HEAD_REGNUM) & ~3;
+ }
+
+ /* Instead of this nasty cast, add a method pvoid() that prints out a
+@@ -5468,62 +2476,6 @@
+ /* We can leave the tail's space the same, since there's no jump. */
+ }
+
+-/* Same as hppa32_store_return_value(), but for the PA64 ABI. */
+-
+-void
+-hppa64_store_return_value (struct type *type, char *valbuf)
+-{
+- if (TYPE_CODE (type) == TYPE_CODE_FLT)
+- deprecated_write_register_bytes
+- (DEPRECATED_REGISTER_BYTE (FP4_REGNUM)
+- + DEPRECATED_REGISTER_SIZE - TYPE_LENGTH (type),
+- valbuf, TYPE_LENGTH (type));
+- else if (is_integral_type(type))
+- deprecated_write_register_bytes
+- (DEPRECATED_REGISTER_BYTE (28)
+- + DEPRECATED_REGISTER_SIZE - TYPE_LENGTH (type),
+- valbuf, TYPE_LENGTH (type));
+- else if (TYPE_LENGTH (type) <= 8)
+- deprecated_write_register_bytes
+- (DEPRECATED_REGISTER_BYTE (28),valbuf, TYPE_LENGTH (type));
+- else if (TYPE_LENGTH (type) <= 16)
+- {
+- deprecated_write_register_bytes (DEPRECATED_REGISTER_BYTE (28),valbuf, 8);
+- deprecated_write_register_bytes
+- (DEPRECATED_REGISTER_BYTE (29), valbuf + 8, TYPE_LENGTH (type) - 8);
+- }
+-}
+-
+-/* Same as hppa32_extract_return_value but for the PA64 ABI case. */
+-
+-void
+-hppa64_extract_return_value (struct type *type, char *regbuf, char *valbuf)
+-{
+- /* RM: Floats are returned in FR4R, doubles in FR4.
+- Integral values are in r28, padded on the left.
+- Aggregates less that 65 bits are in r28, right padded.
+- Aggregates upto 128 bits are in r28 and r29, right padded. */
+- if (TYPE_CODE (type) == TYPE_CODE_FLT)
+- memcpy (valbuf,
+- regbuf + DEPRECATED_REGISTER_BYTE (FP4_REGNUM)
+- + DEPRECATED_REGISTER_SIZE - TYPE_LENGTH (type),
+- TYPE_LENGTH (type));
+- else if (is_integral_type(type))
+- memcpy (valbuf,
+- regbuf + DEPRECATED_REGISTER_BYTE (28)
+- + DEPRECATED_REGISTER_SIZE - TYPE_LENGTH (type),
+- TYPE_LENGTH (type));
+- else if (TYPE_LENGTH (type) <= 8)
+- memcpy (valbuf, regbuf + DEPRECATED_REGISTER_BYTE (28),
+- TYPE_LENGTH (type));
+- else if (TYPE_LENGTH (type) <= 16)
+- {
+- memcpy (valbuf, regbuf + DEPRECATED_REGISTER_BYTE (28), 8);
+- memcpy (valbuf + 8, regbuf + DEPRECATED_REGISTER_BYTE (29),
+- TYPE_LENGTH (type) - 8);
+- }
+-}
+-
+ int
+ hppa_reg_struct_has_addr (int gcc_p, struct type *type)
+ {
+@@ -5539,13 +2491,6 @@
+ return (lhs > rhs);
+ }
+
+-CORE_ADDR
+-hppa64_stack_align (CORE_ADDR sp)
+-{
+- /* The PA64 ABI mandates a 16 byte stack alignment. */
+- return ((sp % 16) ? (sp + 15) & -16 : sp);
+-}
+-
+ int
+ hppa_pc_requires_run_before_use (CORE_ADDR pc)
+ {
+@@ -5586,56 +2531,30 @@
+ return ((ipsw & 0x00200000) && !(flags & 0x2));
+ }
+
+-int
+-hppa_register_raw_size (int reg_nr)
+-{
+- /* All registers have the same size. */
+- return DEPRECATED_REGISTER_SIZE;
+-}
+-
+-/* Index within the register vector of the first byte of the space i
+- used for register REG_NR. */
+-
+-int
+-hppa_register_byte (int reg_nr)
+-{
+- struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+-
+- return reg_nr * tdep->bytes_per_address;
+-}
+-
+ /* Return the GDB type object for the "standard" data type of data
+ in register N. */
+
+-struct type *
+-hppa32_register_virtual_type (int reg_nr)
++static struct type *
++hppa32_register_type (struct gdbarch *gdbarch, int reg_nr)
+ {
+ if (reg_nr < FP4_REGNUM)
+- return builtin_type_int;
++ return builtin_type_uint32;
+ else
+- return builtin_type_float;
++ return builtin_type_ieee_single_big;
+ }
+
+ /* Return the GDB type object for the "standard" data type of data
+ in register N. hppa64 version. */
+
+-struct type *
+-hppa64_register_virtual_type (int reg_nr)
++static struct type *
++hppa64_register_type (struct gdbarch *gdbarch, int reg_nr)
+ {
+ if (reg_nr < FP4_REGNUM)
+- return builtin_type_unsigned_long_long;
++ return builtin_type_uint64;
+ else
+- return builtin_type_double;
++ return builtin_type_ieee_double_big;
+ }
+
+-/* Store the address of the place in which to copy the structure the
+- subroutine will return. This is called from call_function. */
+-
+-void
+-hppa_store_struct_return (CORE_ADDR addr, CORE_ADDR sp)
+-{
+- write_register (28, addr);
+-}
+ /* Return True if REGNUM is not a register available to the user
+ through ptrace(). */
+
+@@ -5746,24 +2665,18 @@
+ case 4:
+ set_gdbarch_num_regs (gdbarch, hppa32_num_regs);
+ set_gdbarch_register_name (gdbarch, hppa32_register_name);
+- set_gdbarch_deprecated_register_virtual_type
+- (gdbarch, hppa32_register_virtual_type);
++ set_gdbarch_register_type (gdbarch, hppa32_register_type);
+ break;
+ case 8:
+ set_gdbarch_num_regs (gdbarch, hppa64_num_regs);
+ set_gdbarch_register_name (gdbarch, hppa64_register_name);
+- set_gdbarch_deprecated_register_virtual_type
+- (gdbarch, hppa64_register_virtual_type);
++ set_gdbarch_register_type (gdbarch, hppa64_register_type);
+ break;
+ default:
+ internal_error (__FILE__, __LINE__, "Unsupported address size: %d",
+ tdep->bytes_per_address);
+ }
+
+- /* The following gdbarch vector elements depend on other parts of this
+- vector which have been set above, depending on the ABI. */
+- set_gdbarch_deprecated_register_bytes
+- (gdbarch, gdbarch_num_regs (gdbarch) * tdep->bytes_per_address);
+ set_gdbarch_long_bit (gdbarch, tdep->bytes_per_address * TARGET_CHAR_BIT);
+ set_gdbarch_ptr_bit (gdbarch, tdep->bytes_per_address * TARGET_CHAR_BIT);
+
+@@ -5781,23 +2694,14 @@
+ set_gdbarch_in_solib_return_trampoline (gdbarch,
+ hppa_in_solib_return_trampoline);
+ set_gdbarch_inner_than (gdbarch, hppa_inner_than);
+- set_gdbarch_deprecated_register_size (gdbarch, tdep->bytes_per_address);
+- set_gdbarch_deprecated_fp_regnum (gdbarch, 3);
+- set_gdbarch_sp_regnum (gdbarch, 30);
+- set_gdbarch_fp0_regnum (gdbarch, 64);
+- set_gdbarch_pc_regnum (gdbarch, PCOQ_HEAD_REGNUM);
+- set_gdbarch_deprecated_register_raw_size (gdbarch, hppa_register_raw_size);
+- set_gdbarch_deprecated_register_byte (gdbarch, hppa_register_byte);
+- set_gdbarch_deprecated_register_virtual_size (gdbarch, hppa_register_raw_size);
+- set_gdbarch_deprecated_max_register_raw_size (gdbarch, tdep->bytes_per_address);
+- set_gdbarch_deprecated_max_register_virtual_size (gdbarch, 8);
++ set_gdbarch_sp_regnum (gdbarch, HPPA_SP_REGNUM);
++ set_gdbarch_fp0_regnum (gdbarch, HPPA_FP0_REGNUM);
+ set_gdbarch_cannot_store_register (gdbarch, hppa_cannot_store_register);
+ set_gdbarch_addr_bits_remove (gdbarch, hppa_smash_text_address);
+ set_gdbarch_smash_text_address (gdbarch, hppa_smash_text_address);
+ set_gdbarch_believe_pcc_promotion (gdbarch, 1);
+ set_gdbarch_read_pc (gdbarch, hppa_target_read_pc);
+ set_gdbarch_write_pc (gdbarch, hppa_target_write_pc);
+- set_gdbarch_deprecated_target_read_fp (gdbarch, hppa_target_read_fp);
+
+ /* Helper for function argument information. */
+ set_gdbarch_fetch_pointer_argument (gdbarch, hppa_fetch_pointer_argument);
+@@ -5818,26 +2722,11 @@
+ set_gdbarch_frame_align (gdbarch, hppa32_frame_align);
+ break;
+ case 8:
+- if (0)
+- {
+- set_gdbarch_push_dummy_call (gdbarch, hppa64_push_dummy_call);
+- set_gdbarch_frame_align (gdbarch, hppa64_frame_align);
+- break;
+- }
+- else
+- {
+- set_gdbarch_deprecated_call_dummy_breakpoint_offset (gdbarch, hppa64_call_dummy_breakpoint_offset);
+- set_gdbarch_deprecated_call_dummy_length (gdbarch, hppa64_call_dummy_length);
+- set_gdbarch_deprecated_stack_align (gdbarch, hppa64_stack_align);
+- break;
+- set_gdbarch_deprecated_push_dummy_frame (gdbarch, hppa_push_dummy_frame);
+- /* set_gdbarch_deprecated_fix_call_dummy (gdbarch, hppa_fix_call_dummy); */
+- set_gdbarch_deprecated_push_arguments (gdbarch, hppa_push_arguments);
+- set_gdbarch_deprecated_use_generic_dummy_frames (gdbarch, 0);
+- set_gdbarch_deprecated_pc_in_call_dummy (gdbarch, deprecated_pc_in_call_dummy_on_stack);
+- set_gdbarch_call_dummy_location (gdbarch, ON_STACK);
+- }
++ set_gdbarch_push_dummy_call (gdbarch, hppa64_push_dummy_call);
++ set_gdbarch_frame_align (gdbarch, hppa64_frame_align);
+ break;
++ default:
++ internal_error (__FILE__, __LINE__, "bad switch");
+ }
+
+ /* Struct return methods. */
+@@ -5847,43 +2736,17 @@
+ set_gdbarch_return_value (gdbarch, hppa32_return_value);
+ break;
+ case 8:
+- if (0)
+- set_gdbarch_return_value (gdbarch, hppa64_return_value);
+- else
+- {
+- set_gdbarch_deprecated_extract_return_value (gdbarch, hppa64_extract_return_value);
+- set_gdbarch_use_struct_convention (gdbarch, hppa64_use_struct_convention);
+- set_gdbarch_deprecated_store_return_value (gdbarch, hppa64_store_return_value);
+- set_gdbarch_deprecated_store_struct_return (gdbarch, hppa_store_struct_return);
+- }
++ set_gdbarch_return_value (gdbarch, hppa64_return_value);
+ break;
+ default:
+ internal_error (__FILE__, __LINE__, "bad switch");
+ }
+
+ /* Frame unwind methods. */
+- switch (tdep->bytes_per_address)
+- {
+- case 4:
+- set_gdbarch_unwind_dummy_id (gdbarch, hppa_unwind_dummy_id);
+- set_gdbarch_unwind_pc (gdbarch, hppa_unwind_pc);
+- frame_unwind_append_sniffer (gdbarch, hppa_frame_unwind_sniffer);
+- frame_base_append_sniffer (gdbarch, hppa_frame_base_sniffer);
+- break;
+- case 8:
+- set_gdbarch_deprecated_saved_pc_after_call (gdbarch, hppa_saved_pc_after_call);
+- set_gdbarch_deprecated_init_frame_pc (gdbarch, deprecated_init_frame_pc_default);
+- set_gdbarch_deprecated_frame_init_saved_regs (gdbarch, hppa_frame_init_saved_regs);
+- set_gdbarch_deprecated_init_extra_frame_info (gdbarch, hppa_init_extra_frame_info);
+- set_gdbarch_deprecated_frame_chain (gdbarch, hppa_frame_chain);
+- set_gdbarch_deprecated_frame_chain_valid (gdbarch, hppa_frame_chain_valid);
+- set_gdbarch_deprecated_frameless_function_invocation (gdbarch, hppa_frameless_function_invocation);
+- set_gdbarch_deprecated_frame_saved_pc (gdbarch, hppa_frame_saved_pc);
+- set_gdbarch_deprecated_pop_frame (gdbarch, hppa_pop_frame);
+- break;
+- default:
+- internal_error (__FILE__, __LINE__, "bad switch");
+- }
++ set_gdbarch_unwind_dummy_id (gdbarch, hppa_unwind_dummy_id);
++ set_gdbarch_unwind_pc (gdbarch, hppa_unwind_pc);
++ frame_unwind_append_sniffer (gdbarch, hppa_frame_unwind_sniffer);
++ frame_base_append_sniffer (gdbarch, hppa_frame_base_sniffer);
+
+ /* Hook in ABI-specific overrides, if they have been registered. */
+ gdbarch_init_osabi (info, gdbarch);
diff --git a/sys-devel/gdb/gdb-6.1.ebuild b/sys-devel/gdb/gdb-6.1.ebuild
index 98f210eea80f..d693832dd52a 100644
--- a/sys-devel/gdb/gdb-6.1.ebuild
+++ b/sys-devel/gdb/gdb-6.1.ebuild
@@ -1,6 +1,6 @@
# Copyright 1999-2004 Gentoo Technologies, Inc.
# Distributed under the terms of the GNU General Public License v2
-# $Header: /var/cvsroot/gentoo-x86/sys-devel/gdb/gdb-6.1.ebuild,v 1.2 2004/05/28 16:29:29 tgall Exp $
+# $Header: /var/cvsroot/gentoo-x86/sys-devel/gdb/gdb-6.1.ebuild,v 1.3 2004/05/30 01:35:27 gmsoft Exp $
inherit flag-o-matic eutils
@@ -20,6 +20,7 @@ src_unpack() {
unpack ${A}
cd ${S}
epatch ${FILESDIR}/gdb-6.1-ppc64-01.patch
+ epatch ${FILESDIR}/gdb-6.1-hppa.patch
}
src_compile() {