diff options
Diffstat (limited to 'sys-devel/gdb/files/gdb-6.1-hppa.patch')
-rw-r--r-- | sys-devel/gdb/files/gdb-6.1-hppa.patch | 5816 |
1 files changed, 5816 insertions, 0 deletions
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 ¤t_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, ®_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, ®_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 ¤t_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); |