* elf32-xtensa.c (ebb_propose_action): Fix argument order.
[deliverable/binutils-gdb.git] / gdb / hppa-tdep.c
index 5e84782ff03802a840683b3d1517b66e6b634c46..f4cca55a34e42f8ab49f943a77ee06ab1a408dca 100644 (file)
    Boston, MA 02111-1307, USA.  */
 
 #include "defs.h"
-#include "frame.h"
 #include "bfd.h"
 #include "inferior.h"
-#include "value.h"
 #include "regcache.h"
 #include "completer.h"
-#include "language.h"
 #include "osabi.h"
 #include "gdb_assert.h"
-#include "infttrace.h"
 #include "arch-utils.h"
 /* For argument passing to the inferior */
 #include "symtab.h"
-#include "infcall.h"
 #include "dis-asm.h"
 #include "trad-frame.h"
 #include "frame-unwind.h"
 #include "frame-base.h"
 
-#include "gdb_stat.h"
-#include "gdb_wait.h"
-
 #include "gdbcore.h"
 #include "gdbcmd.h"
-#include "target.h"
-#include "symfile.h"
 #include "objfiles.h"
 #include "hppa-tdep.h"
 
@@ -74,41 +64,10 @@ const struct objfile_data *hppa_objfile_priv_data = NULL;
 #define MASK_14 0x3fff
 #define MASK_21 0x1fffff
 
-/* Define offsets into the call dummy for the _sr4export address.
-   See comments related to CALL_DUMMY for more info.  */
-#define SR4EXPORT_LDIL_OFFSET (HPPA_INSTRUCTION_SIZE * 12)
-#define SR4EXPORT_LDO_OFFSET (HPPA_INSTRUCTION_SIZE * 13)
-
-/* To support detection of the pseudo-initial frame
-   that threads have. */
-#define THREAD_INITIAL_FRAME_SYMBOL  "__pthread_exit"
-#define THREAD_INITIAL_FRAME_SYM_LEN  sizeof(THREAD_INITIAL_FRAME_SYMBOL)
-
 /* Sizes (in bytes) of the native unwind entries.  */
 #define UNWIND_ENTRY_SIZE 16
 #define STUB_UNWIND_ENTRY_SIZE 8
 
-static void unwind_command (char *, int);
-
-static int hppa_alignof (struct type *);
-
-static int prologue_inst_adjust_sp (unsigned long);
-
-static int is_branch (unsigned long);
-
-static int inst_saves_gr (unsigned long);
-
-static int inst_saves_fr (unsigned long);
-
-static int compare_unwind_entries (const void *, const void *);
-
-static void read_unwind_info (struct objfile *);
-
-static void internalize_unwinds (struct objfile *,
-                                struct unwind_table_entry *,
-                                asection *, unsigned int,
-                                unsigned int, CORE_ADDR);
-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.  */
 int hppa_pc_requires_run_before_use (CORE_ADDR pc);
@@ -126,7 +85,7 @@ hppa32_return_value (struct gdbarch *gdbarch,
       /* The value always lives in the right hand end of the register
         (or register pair)?  */
       int b;
-      int reg = TYPE_CODE (type) == TYPE_CODE_FLT ? FP4_REGNUM : 28;
+      int reg = TYPE_CODE (type) == TYPE_CODE_FLT ? HPPA_FP4_REGNUM : 28;
       int part = TYPE_LENGTH (type) % 4;
       /* The left hand register contains only part of the value,
         transfer that first so that the rest can be xfered as entire
@@ -169,19 +128,19 @@ hppa64_return_value (struct gdbarch *gdbarch,
       && TYPE_LENGTH (type) <= 8)
     {
       /* Floats are right aligned?  */
-      int offset = register_size (gdbarch, FP4_REGNUM) - TYPE_LENGTH (type);
+      int offset = register_size (gdbarch, HPPA_FP4_REGNUM) - TYPE_LENGTH (type);
       if (readbuf != NULL)
-       regcache_cooked_read_part (regcache, FP4_REGNUM, offset,
+       regcache_cooked_read_part (regcache, HPPA_FP4_REGNUM, offset,
                                   TYPE_LENGTH (type), readbuf);
       if (writebuf != NULL)
-       regcache_cooked_write_part (regcache, FP4_REGNUM, offset,
+       regcache_cooked_write_part (regcache, HPPA_FP4_REGNUM, offset,
                                    TYPE_LENGTH (type), writebuf);
       return RETURN_VALUE_REGISTER_CONVENTION;
     }
   else if (TYPE_LENGTH (type) <= 8 && is_integral_type (type))
     {
       /* Integrals are right aligned.  */
-      int offset = register_size (gdbarch, FP4_REGNUM) - TYPE_LENGTH (type);
+      int offset = register_size (gdbarch, HPPA_FP4_REGNUM) - TYPE_LENGTH (type);
       if (readbuf != NULL)
        regcache_cooked_read_part (regcache, 28, offset,
                                   TYPE_LENGTH (type), readbuf);
@@ -303,6 +262,18 @@ hppa_extract_17 (unsigned word)
                      hppa_get_field (word, 11, 15) << 11 |
                      (word & 0x1) << 16, 17) << 2;
 }
+
+CORE_ADDR 
+hppa_symbol_address(const char *sym)
+{
+  struct minimal_symbol *minsym;
+
+  minsym = lookup_minimal_symbol (sym, NULL, NULL);
+  if (minsym)
+    return SYMBOL_VALUE_ADDRESS (minsym);
+  else
+    return (CORE_ADDR)-1;
+}
 \f
 
 /* Compare the start address for two unwind entries returning 1 if 
@@ -661,7 +632,7 @@ hppa_breakpoint_from_pc (CORE_ADDR *pc, int *len)
 
 /* Return the name of a register.  */
 
-const char *
+static const char *
 hppa32_register_name (int i)
 {
   static char *names[] = {
@@ -704,7 +675,7 @@ hppa32_register_name (int i)
     return names[i];
 }
 
-const char *
+static const char *
 hppa64_register_name (int i)
 {
   static char *names[] = {
@@ -749,8 +720,8 @@ hppa64_register_name (int i)
    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,
+static CORE_ADDR
+hppa32_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                        struct regcache *regcache, CORE_ADDR bp_addr,
                        int nargs, struct value **args, CORE_ADDR sp,
                        int struct_return, CORE_ADDR struct_addr)
@@ -768,6 +739,12 @@ hppa32_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
   /* Two passes.  First pass computes the location of everything,
      second pass writes the bytes out.  */
   int write_pass;
+
+  /* Global pointer (r19) of the function we are trying to call.  */
+  CORE_ADDR gp;
+
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
   for (write_pass = 0; write_pass < 2; write_pass++)
     {
       CORE_ADDR struct_ptr = 0;
@@ -781,7 +758,7 @@ hppa32_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
       for (i = 0; i < nargs; i++)
        {
          struct value *arg = args[i];
-         struct type *type = check_typedef (VALUE_TYPE (arg));
+         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];
@@ -826,7 +803,7 @@ hppa32_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
                 the higher-ordered word is stored in the lower-ordered
                 argument, and even though it is a 8-byte quantity the
                 registers need not be 8-byte aligned.  */
-             if (param_len > 4)
+             if (param_len > 4 && param_len < 8)
                small_struct = 1;
            }
 
@@ -888,11 +865,16 @@ hppa32_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
   if (struct_return)
     write_register (28, struct_addr);
 
+  gp = tdep->find_global_pointer (function);
+
+  if (gp != 0)
+    write_register (19, gp);
+
   /* Set the return address.  */
-  regcache_cooked_write_unsigned (regcache, RP_REGNUM, bp_addr);
+  regcache_cooked_write_unsigned (regcache, HPPA_RP_REGNUM, bp_addr);
 
   /* Update the Stack Pointer.  */
-  regcache_cooked_write_unsigned (regcache, SP_REGNUM, param_end);
+  regcache_cooked_write_unsigned (regcache, HPPA_SP_REGNUM, param_end);
 
   return param_end;
 }
@@ -910,8 +892,8 @@ hppa32_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
    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,
+static CORE_ADDR
+hppa64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                        struct regcache *regcache, CORE_ADDR bp_addr,
                        int nargs, struct value **args, CORE_ADDR sp,
                        int struct_return, CORE_ADDR struct_addr)
@@ -940,7 +922,7 @@ hppa64_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
       for (i = 0; i < nargs; i++)
        {
          struct value *arg = args[i];
-         struct type *type = check_typedef (VALUE_TYPE (arg));
+         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)
@@ -1011,15 +993,31 @@ hppa64_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
     write_register (28, struct_addr);
 
   /* Set the return address.  */
-  regcache_cooked_write_unsigned (regcache, RP_REGNUM, bp_addr);
+  regcache_cooked_write_unsigned (regcache, HPPA_RP_REGNUM, bp_addr);
 
   /* Update the Stack Pointer.  */
-  regcache_cooked_write_unsigned (regcache, SP_REGNUM, param_end + 64);
+  regcache_cooked_write_unsigned (regcache, HPPA_SP_REGNUM, param_end + 64);
 
   /* The stack will have 32 bytes of additional space for a frame marker.  */
   return param_end + 64;
 }
 
+static CORE_ADDR
+hppa32_convert_from_func_ptr_addr (struct gdbarch *gdbarch,
+                                  CORE_ADDR addr,
+                                  struct target_ops *targ)
+{
+  if (addr & 2)
+    {
+      CORE_ADDR plabel;
+
+      plabel = addr & ~3;
+      target_read_memory(plabel, (char *)&addr, 4);
+    }
+
+  return addr;
+}
+
 static CORE_ADDR
 hppa32_frame_align (struct gdbarch *gdbarch, CORE_ADDR addr)
 {
@@ -1044,7 +1042,7 @@ hppa64_frame_align (struct gdbarch *gdbarch, CORE_ADDR addr)
 static CORE_ADDR
 hppa_target_read_pc (ptid_t ptid)
 {
-  int flags = read_register_pid (FLAGS_REGNUM, ptid);
+  int flags = read_register_pid (HPPA_FLAGS_REGNUM, ptid);
 
   /* The following test does not belong here.  It is OS-specific, and belongs
      in native code.  */
@@ -1052,7 +1050,7 @@ hppa_target_read_pc (ptid_t ptid)
   if (flags & 2)
     return read_register_pid (31, ptid) & ~0x3;
 
-  return read_register_pid (PCOQ_HEAD_REGNUM, ptid) & ~0x3;
+  return read_register_pid (HPPA_PCOQ_HEAD_REGNUM, ptid) & ~0x3;
 }
 
 /* Write out the PC.  If currently in a syscall, then also write the new
@@ -1061,7 +1059,7 @@ hppa_target_read_pc (ptid_t ptid)
 static void
 hppa_target_write_pc (CORE_ADDR v, ptid_t ptid)
 {
-  int flags = read_register_pid (FLAGS_REGNUM, ptid);
+  int flags = read_register_pid (HPPA_FLAGS_REGNUM, ptid);
 
   /* The following test does not belong here.  It is OS-specific, and belongs
      in native code.  */
@@ -1071,8 +1069,8 @@ hppa_target_write_pc (CORE_ADDR v, ptid_t ptid)
   if (flags & 2)
     write_register_pid (31, v | 0x3, ptid);
 
-  write_register_pid (PCOQ_HEAD_REGNUM, v, ptid);
-  write_register_pid (PCOQ_TAIL_REGNUM, v + 4, ptid);
+  write_register_pid (HPPA_PCOQ_HEAD_REGNUM, v, ptid);
+  write_register_pid (HPPA_PCOQ_TAIL_REGNUM, v + 4, ptid);
 }
 
 /* return the alignment of a type in bytes. Structures have the maximum
@@ -1249,14 +1247,15 @@ inst_saves_fr (unsigned long inst)
    be in the prologue.  */
 
 
-CORE_ADDR
-skip_prologue_hard_way (CORE_ADDR pc)
+static CORE_ADDR
+skip_prologue_hard_way (CORE_ADDR pc, int stop_before_branch)
 {
   char buf[4];
   CORE_ADDR orig_pc = pc;
   unsigned long inst, stack_remaining, save_gr, save_fr, save_rp, save_sp;
   unsigned long args_stored, status, i, restart_gr, restart_fr;
   struct unwind_table_entry *u;
+  int final_iteration;
 
   restart_gr = 0;
   restart_fr = 0;
@@ -1300,6 +1299,8 @@ restart:
     save_fr |= (1 << i);
   save_fr &= ~restart_fr;
 
+  final_iteration = 0;
+
   /* 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
@@ -1329,7 +1330,7 @@ restart:
       old_save_sp = save_sp;
       old_stack_remaining = stack_remaining;
 
-      status = target_read_memory (pc, buf, 4);
+      status = deprecated_read_memory_nobpt (pc, buf, 4);
       inst = extract_unsigned_integer (buf, 4);
 
       /* Yow! */
@@ -1378,7 +1379,7 @@ restart:
          while (reg_num >= (TARGET_PTR_BIT == 64 ? 19 : 23) && reg_num <= 26)
            {
              pc += 4;
-             status = target_read_memory (pc, buf, 4);
+             status = deprecated_read_memory_nobpt (pc, buf, 4);
              inst = extract_unsigned_integer (buf, 4);
              if (status != 0)
                return pc;
@@ -1391,7 +1392,7 @@ restart:
       reg_num = inst_saves_fr (inst);
       save_fr &= ~(1 << reg_num);
 
-      status = target_read_memory (pc + 4, buf, 4);
+      status = deprecated_read_memory_nobpt (pc + 4, buf, 4);
       next_inst = extract_unsigned_integer (buf, 4);
 
       /* Yow! */
@@ -1418,13 +1419,13 @@ restart:
          while (reg_num >= 4 && reg_num <= (TARGET_PTR_BIT == 64 ? 11 : 7))
            {
              pc += 8;
-             status = target_read_memory (pc, buf, 4);
+             status = deprecated_read_memory_nobpt (pc, buf, 4);
              inst = extract_unsigned_integer (buf, 4);
              if (status != 0)
                return pc;
              if ((inst & 0xfc000000) != 0x34000000)
                break;
-             status = target_read_memory (pc + 4, buf, 4);
+             status = deprecated_read_memory_nobpt (pc + 4, buf, 4);
              next_inst = extract_unsigned_integer (buf, 4);
              if (status != 0)
                return pc;
@@ -1436,7 +1437,7 @@ restart:
 
       /* Quit if we hit any kind of branch.  This can happen if a prologue
          instruction is in the delay slot of the first call/branch.  */
-      if (is_branch (inst))
+      if (is_branch (inst) && stop_before_branch)
        break;
 
       /* What a crock.  The HP compilers set args_stored even if no
@@ -1457,6 +1458,13 @@ restart:
 
       /* Bump the PC.  */
       pc += 4;
+
+      /* !stop_before_branch, so also look at the insn in the delay slot 
+         of the branch.  */
+      if (final_iteration)
+       break;
+      if (is_branch (inst))
+       final_iteration = 1;
     }
 
   /* We've got a tenative location for the end of the prologue.  However
@@ -1515,12 +1523,13 @@ after_prologue (CORE_ADDR pc)
 
 /* 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.  */
+   returns an address that (if we're lucky) follows the prologue.  
+   
+   hppa_skip_prologue is called by gdb to place a breakpoint in a function.
+   It doesn't necessarily skips all the insns in the prologue. In fact
+   we might not want to skip all the insns because a prologue insn may
+   appear in the delay slot of the first branch, and we don't want to
+   skip over the branch in that case.  */
 
 static CORE_ADDR
 hppa_skip_prologue (CORE_ADDR pc)
@@ -1545,7 +1554,7 @@ hppa_skip_prologue (CORE_ADDR pc)
   if (post_prologue_pc != 0)
     return max (pc, post_prologue_pc);
   else
-    return (skip_prologue_hard_way (pc));
+    return (skip_prologue_hard_way (pc, 1));
 }
 
 struct hppa_frame_cache
@@ -1564,6 +1573,7 @@ hppa_frame_cache (struct frame_info *next_frame, void **this_cache)
   long frame_size;
   struct unwind_table_entry *u;
   CORE_ADDR prologue_end;
+  int fp_in_r1 = 0;
   int i;
 
   if (hppa_debug)
@@ -1582,7 +1592,7 @@ hppa_frame_cache (struct frame_info *next_frame, void **this_cache)
   cache->saved_regs = trad_frame_alloc_saved_regs (next_frame);
 
   /* Yow! */
-  u = find_unwind_entry (frame_func_unwind (next_frame));
+  u = find_unwind_entry (frame_pc_unwind (next_frame));
   if (!u)
     {
       if (hppa_debug)
@@ -1627,12 +1637,24 @@ hppa_frame_cache (struct frame_info *next_frame, void **this_cache)
     int looking_for_rp = u->Save_RP;
     int fp_loc = -1;
 
-    /* We have to use hppa_skip_prologue instead of just 
+    /* We have to use skip_prologue_hard_way instead of just 
        skip_prologue_using_sal, in case we stepped into a function without
        symbol information.  hppa_skip_prologue also bounds the returned
        pc by the passed in pc, so it will not return a pc in the next
-       function.  */
-    prologue_end = hppa_skip_prologue (frame_func_unwind (next_frame));
+       function.  
+       
+       We used to call hppa_skip_prologue to find the end of the prologue,
+       but if some non-prologue instructions get scheduled into the prologue,
+       and the program is compiled with debug information, the "easy" way
+       in hppa_skip_prologue will return a prologue end that is too early
+       for us to notice any potential frame adjustments.  */
+
+    /* We used to use frame_func_unwind () to locate the beginning of the
+       function to pass to skip_prologue ().  However, when objects are 
+       compiled without debug symbols, frame_func_unwind can return the wrong 
+       function (or 0).  We can do better than that by using unwind records.  */
+
+    prologue_end = skip_prologue_hard_way (u->region_start, 0);
     end_pc = frame_pc_unwind (next_frame);
 
     if (prologue_end != 0 && end_pc > prologue_end)
@@ -1640,7 +1662,7 @@ hppa_frame_cache (struct frame_info *next_frame, void **this_cache)
 
     frame_size = 0;
 
-    for (pc = frame_func_unwind (next_frame);
+    for (pc = u->region_start;
         ((saved_gr_mask || saved_fr_mask
           || looking_for_sp || looking_for_rp
           || frame_size < (u->Total_frame_size << 3))
@@ -1649,8 +1671,16 @@ hppa_frame_cache (struct frame_info *next_frame, void **this_cache)
       {
        int reg;
        char buf4[4];
-       long status = target_read_memory (pc, buf4, sizeof buf4);
-       long inst = extract_unsigned_integer (buf4, sizeof buf4);
+       long inst;
+
+       if (!safe_frame_unwind_memory (next_frame, pc, buf4, 
+                                      sizeof buf4)) 
+         {
+           error ("Cannot read instruction at 0x%s\n", paddr_nz (pc));
+           return (*this_cache);
+         }
+
+       inst = extract_unsigned_integer (buf4, sizeof buf4);
 
        /* Note the interesting effects of this instruction.  */
        frame_size += prologue_inst_adjust_sp (inst);
@@ -1660,12 +1690,17 @@ hppa_frame_cache (struct frame_info *next_frame, void **this_cache)
        if (inst == 0x6bc23fd9) /* stw rp,-0x14(sr0,sp) */
          {
            looking_for_rp = 0;
-           cache->saved_regs[RP_REGNUM].addr = -20;
+           cache->saved_regs[HPPA_RP_REGNUM].addr = -20;
+         }
+       else if (inst == 0x6bc23fd1) /* stw rp,-0x18(sr0,sp) */
+         {
+           looking_for_rp = 0;
+           cache->saved_regs[HPPA_RP_REGNUM].addr = -24;
          }
        else if (inst == 0x0fc212c1) /* std rp,-0x10(sr0,sp) */
          {
            looking_for_rp = 0;
-           cache->saved_regs[RP_REGNUM].addr = -16;
+           cache->saved_regs[HPPA_RP_REGNUM].addr = -16;
          }
        
        /* Check to see if we saved SP into the stack.  This also
@@ -1677,6 +1712,10 @@ hppa_frame_cache (struct frame_info *next_frame, void **this_cache)
            looking_for_sp = 0;
            cache->saved_regs[HPPA_FP_REGNUM].addr = 0;
          }
+       else if (inst == 0x08030241) /* copy %r3, %r1 */
+         {
+           fp_in_r1 = 1;
+         }
        
        /* Account for general and floating-point register saves.  */
        reg = inst_saves_gr (inst);
@@ -1736,7 +1775,7 @@ hppa_frame_cache (struct frame_info *next_frame, void **this_cache)
                /* 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.  */
-               cache->saved_regs[reg + FP4_REGNUM + 4].addr = 0;
+               cache->saved_regs[reg + HPPA_FP4_REGNUM + 4].addr = 0;
                fp_loc = 8;
              }
            else
@@ -1761,6 +1800,7 @@ hppa_frame_cache (struct frame_info *next_frame, void **this_cache)
        the current function (and is thus equivalent to the "saved"
        stack pointer.  */
     CORE_ADDR this_sp = frame_unwind_register_unsigned (next_frame, HPPA_SP_REGNUM);
+    CORE_ADDR fp;
 
     if (hppa_debug)
       fprintf_unfiltered (gdb_stdlog, " (this_sp=0x%s, pc=0x%s, "
@@ -1769,10 +1809,38 @@ hppa_frame_cache (struct frame_info *next_frame, void **this_cache)
                          paddr_nz (frame_pc_unwind (next_frame)),
                          paddr_nz (prologue_end));
 
-    if (frame_pc_unwind (next_frame) >= prologue_end)
+     /* Check to see if a frame pointer is available, and use it for
+        frame unwinding if it is.
+        There are some situations where we need to rely on the frame
+        pointer to do stack unwinding.  For example, if a function calls
+        alloca (), the stack pointer can get adjusted inside the body of
+        the function.  In this case, the ABI requires that the compiler
+        maintain a frame pointer for the function.
+        The unwind record has a flag (alloca_frame) that indicates that
+        a function has a variable frame; unfortunately, gcc/binutils 
+        does not set this flag.  Instead, whenever a frame pointer is used
+        and saved on the stack, the Save_SP flag is set.  We use this to
+        decide whether to use the frame pointer for unwinding.
+       
+        TODO: For the HP compiler, maybe we should use the alloca_frame flag 
+       instead of Save_SP.  */
+     fp = frame_unwind_register_unsigned (next_frame, HPPA_FP_REGNUM);
+     if (frame_pc_unwind (next_frame) >= prologue_end
+         && u->Save_SP && fp != 0)
+      {
+       cache->base = fp;
+       if (hppa_debug)
+         fprintf_unfiltered (gdb_stdlog, " (base=0x%s) [frame pointer] }",
+           paddr_nz (cache->base));
+      }
+     else if (u->Save_SP 
+             && trad_frame_addr_p (cache->saved_regs, HPPA_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.  */
@@ -1781,29 +1849,17 @@ hppa_frame_cache (struct frame_info *next_frame, void **this_cache)
            if (hppa_debug)
              fprintf_unfiltered (gdb_stdlog, " (base=0x%s) [saved] }",
                                  paddr_nz (cache->base));
-          }
-        else
-          {
-            /* The prologue has been slowly allocating stack space.  Adjust
-            the SP back.  */
-            cache->base = this_sp - frame_size;
-           if (hppa_debug)
-             fprintf_unfiltered (gdb_stdlog, " (base=0x%s) [unwind adjust] } ",
-                                 paddr_nz (cache->base));
-
-          }
       }
     else
       {
-       /* This frame has not yet been created. */
-        cache->base = this_sp;
-
+        /* The prologue has been slowly allocating stack space.  Adjust
+          the SP back.  */
+        cache->base = this_sp - frame_size;
        if (hppa_debug)
-         fprintf_unfiltered (gdb_stdlog, " (base=0x%s) [before prologue] } ",
+         fprintf_unfiltered (gdb_stdlog, " (base=0x%s) [unwind adjust] } ",
                              paddr_nz (cache->base));
 
       }
-
     trad_frame_set_value (cache->saved_regs, HPPA_SP_REGNUM, cache->base);
   }
 
@@ -1811,25 +1867,46 @@ hppa_frame_cache (struct frame_info *next_frame, void **this_cache)
      as the return register while normal code uses "rp".  */
   if (u->Millicode)
     {
-      if (trad_frame_addr_p (cache->saved_regs, RP_REGNUM))
-        cache->saved_regs[PCOQ_HEAD_REGNUM] = cache->saved_regs[31];
+      if (trad_frame_addr_p (cache->saved_regs, 31))
+        cache->saved_regs[HPPA_PCOQ_HEAD_REGNUM] = cache->saved_regs[31];
       else
        {
          ULONGEST r31 = frame_unwind_register_unsigned (next_frame, 31);
-         trad_frame_set_value (cache->saved_regs, PCOQ_HEAD_REGNUM, r31);
+         trad_frame_set_value (cache->saved_regs, HPPA_PCOQ_HEAD_REGNUM, r31);
         }
     }
   else
     {
-      if (trad_frame_addr_p (cache->saved_regs, RP_REGNUM))
-        cache->saved_regs[PCOQ_HEAD_REGNUM] = cache->saved_regs[RP_REGNUM];
+      if (trad_frame_addr_p (cache->saved_regs, HPPA_RP_REGNUM))
+        cache->saved_regs[HPPA_PCOQ_HEAD_REGNUM] = cache->saved_regs[HPPA_RP_REGNUM];
       else
        {
-         ULONGEST rp = frame_unwind_register_unsigned (next_frame, RP_REGNUM);
-         trad_frame_set_value (cache->saved_regs, PCOQ_HEAD_REGNUM, rp);
+         ULONGEST rp = frame_unwind_register_unsigned (next_frame, HPPA_RP_REGNUM);
+         trad_frame_set_value (cache->saved_regs, HPPA_PCOQ_HEAD_REGNUM, rp);
        }
     }
 
+  /* If Save_SP is set, then we expect the frame pointer to be saved in the
+     frame.  However, there is a one-insn window where we haven't saved it
+     yet, but we've already clobbered it.  Detect this case and fix it up.
+
+     The prologue sequence for frame-pointer functions is:
+       0: stw %rp, -20(%sp)
+       4: copy %r3, %r1
+       8: copy %sp, %r3
+       c: stw,ma %r1, XX(%sp)
+
+     So if we are at offset c, the r3 value that we want is not yet saved
+     on the stack, but it's been overwritten.  The prologue analyzer will
+     set fp_in_r1 when it sees the copy insn so we know to get the value 
+     from r1 instead.  */
+  if (u->Save_SP && !trad_frame_addr_p (cache->saved_regs, HPPA_FP_REGNUM)
+      && fp_in_r1)
+    {
+      ULONGEST r1 = frame_unwind_register_unsigned (next_frame, 1);
+      trad_frame_set_value (cache->saved_regs, HPPA_FP_REGNUM, r1);
+    }
+
   {
     /* Convert all the offsets into addresses.  */
     int reg;
@@ -1850,48 +1927,26 @@ static void
 hppa_frame_this_id (struct frame_info *next_frame, void **this_cache,
                           struct frame_id *this_id)
 {
-  struct hppa_frame_cache *info = hppa_frame_cache (next_frame, this_cache);
-  (*this_id) = frame_id_build (info->base, frame_func_unwind (next_frame));
+  struct hppa_frame_cache *info;
+  CORE_ADDR pc = frame_pc_unwind (next_frame);
+  struct unwind_table_entry *u;
+
+  info = hppa_frame_cache (next_frame, this_cache);
+  u = find_unwind_entry (pc);
+
+  (*this_id) = frame_id_build (info->base, u->region_start);
 }
 
 static void
 hppa_frame_prev_register (struct frame_info *next_frame,
-                                void **this_cache,
-                                int regnum, int *optimizedp,
-                                enum lval_type *lvalp, CORE_ADDR *addrp,
-                                int *realnump, void *valuep)
+                         void **this_cache,
+                         int regnum, int *optimizedp,
+                         enum lval_type *lvalp, CORE_ADDR *addrp,
+                         int *realnump, void *valuep)
 {
   struct hppa_frame_cache *info = hppa_frame_cache (next_frame, this_cache);
-  struct gdbarch *gdbarch = get_frame_arch (next_frame);
-  if (regnum == PCOQ_TAIL_REGNUM)
-    {
-      /* The PCOQ TAIL, or NPC, needs to be computed from the unwound
-        PC register.  */
-      *optimizedp = 0;
-      *lvalp = not_lval;
-      *addrp = 0;
-      *realnump = 0;
-      if (valuep)
-       {
-         int regsize = register_size (gdbarch, PCOQ_HEAD_REGNUM);
-         CORE_ADDR pc;
-         int optimized;
-         enum lval_type lval;
-         CORE_ADDR addr;
-         int realnum;
-         bfd_byte value[MAX_REGISTER_SIZE];
-         trad_frame_prev_register (next_frame, info->saved_regs,
-                                   PCOQ_HEAD_REGNUM, &optimized, &lval, &addr,
-                                   &realnum, &value);
-         pc = extract_unsigned_integer (&value, regsize);
-         store_unsigned_integer (valuep, regsize, pc + 4);
-       }
-    }
-  else
-    {
-      trad_frame_prev_register (next_frame, info->saved_regs, regnum,
-                               optimizedp, lvalp, addrp, realnump, valuep);
-    }
+  hppa_frame_prev_register_helper (next_frame, info->saved_regs, regnum,
+                                  optimizedp, lvalp, addrp, realnump, valuep);
 }
 
 static const struct frame_unwind hppa_frame_unwind =
@@ -1904,29 +1959,131 @@ static const struct frame_unwind hppa_frame_unwind =
 static const struct frame_unwind *
 hppa_frame_unwind_sniffer (struct frame_info *next_frame)
 {
-  return &hppa_frame_unwind;
+  CORE_ADDR pc = frame_pc_unwind (next_frame);
+
+  if (find_unwind_entry (pc))
+    return &hppa_frame_unwind;
+
+  return NULL;
 }
 
-static CORE_ADDR
-hppa_frame_base_address (struct frame_info *next_frame,
-                               void **this_cache)
+/* This is a generic fallback frame unwinder that kicks in if we fail all
+   the other ones.  Normally we would expect the stub and regular unwinder
+   to work, but in some cases we might hit a function that just doesn't
+   have any unwind information available.  In this case we try to do
+   unwinding solely based on code reading.  This is obviously going to be
+   slow, so only use this as a last resort.  Currently this will only
+   identify the stack and pc for the frame.  */
+
+static struct hppa_frame_cache *
+hppa_fallback_frame_cache (struct frame_info *next_frame, void **this_cache)
 {
-  struct hppa_frame_cache *info = hppa_frame_cache (next_frame,
-                                                          this_cache);
-  return info->base;
+  struct hppa_frame_cache *cache;
+  unsigned int frame_size;
+  int found_rp;
+  CORE_ADDR pc, start_pc, end_pc, cur_pc;
+
+  if (hppa_debug)
+    fprintf_unfiltered (gdb_stdlog, "{ hppa_fallback_frame_cache (frame=%d)-> ",
+      frame_relative_level(next_frame));
+
+  cache = FRAME_OBSTACK_ZALLOC (struct hppa_frame_cache);
+  (*this_cache) = cache;
+  cache->saved_regs = trad_frame_alloc_saved_regs (next_frame);
+
+  pc = frame_func_unwind (next_frame);
+  cur_pc = frame_pc_unwind (next_frame);
+  frame_size = 0;
+  found_rp = 0;
+
+  find_pc_partial_function (pc, NULL, &start_pc, &end_pc);
+
+  if (start_pc == 0 || end_pc == 0)
+    {
+      error ("Cannot find bounds of current function (@0x%s), unwinding will "
+            "fail.", paddr_nz (pc));
+      return cache;
+    }
+
+  if (end_pc > cur_pc)
+    end_pc = cur_pc;
+
+  for (pc = start_pc; pc < end_pc; pc += 4)
+    {
+      unsigned int insn;
+
+      insn = read_memory_unsigned_integer (pc, 4);
+
+      frame_size += prologue_inst_adjust_sp (insn);
+
+      /* There are limited ways to store the return pointer into the
+        stack.  */
+      if (insn == 0x6bc23fd9) /* stw rp,-0x14(sr0,sp) */
+        {
+          cache->saved_regs[HPPA_RP_REGNUM].addr = -20;
+          found_rp = 1;
+        }
+      else if (insn == 0x0fc212c1) /* std rp,-0x10(sr0,sp) */
+        {
+          cache->saved_regs[HPPA_RP_REGNUM].addr = -16;
+          found_rp = 1;
+        }
+    }
+
+  if (hppa_debug)
+    fprintf_unfiltered (gdb_stdlog, " frame_size = %d, found_rp = %d }\n",
+      frame_size, found_rp);
+
+  cache->base = frame_unwind_register_unsigned (next_frame, HPPA_SP_REGNUM) - frame_size;
+  trad_frame_set_value (cache->saved_regs, HPPA_SP_REGNUM, cache->base);
+
+  if (trad_frame_addr_p (cache->saved_regs, HPPA_RP_REGNUM))
+    {
+      cache->saved_regs[HPPA_RP_REGNUM].addr += cache->base;
+      cache->saved_regs[HPPA_PCOQ_HEAD_REGNUM] = cache->saved_regs[HPPA_RP_REGNUM];
+    }
+  else
+    {
+      ULONGEST rp = frame_unwind_register_unsigned (next_frame, HPPA_RP_REGNUM);
+      trad_frame_set_value (cache->saved_regs, HPPA_PCOQ_HEAD_REGNUM, rp);
+    }
+
+  return cache;
+}
+
+static void
+hppa_fallback_frame_this_id (struct frame_info *next_frame, void **this_cache,
+                            struct frame_id *this_id)
+{
+  struct hppa_frame_cache *info = 
+    hppa_fallback_frame_cache (next_frame, this_cache);
+  (*this_id) = frame_id_build (info->base, frame_func_unwind (next_frame));
 }
 
-static const struct frame_base hppa_frame_base = {
-  &hppa_frame_unwind,
-  hppa_frame_base_address,
-  hppa_frame_base_address,
-  hppa_frame_base_address
+static void
+hppa_fallback_frame_prev_register (struct frame_info *next_frame,
+                         void **this_cache,
+                         int regnum, int *optimizedp,
+                         enum lval_type *lvalp, CORE_ADDR *addrp,
+                         int *realnump, void *valuep)
+{
+  struct hppa_frame_cache *info = 
+    hppa_fallback_frame_cache (next_frame, this_cache);
+  hppa_frame_prev_register_helper (next_frame, info->saved_regs, regnum,
+                                  optimizedp, lvalp, addrp, realnump, valuep);
+}
+
+static const struct frame_unwind hppa_fallback_frame_unwind =
+{
+  NORMAL_FRAME,
+  hppa_fallback_frame_this_id,
+  hppa_fallback_frame_prev_register
 };
 
-static const struct frame_base *
-hppa_frame_base_sniffer (struct frame_info *next_frame)
+static const struct frame_unwind *
+hppa_fallback_unwind_sniffer (struct frame_info *next_frame)
 {
-  return &hppa_frame_base;
+  return &hppa_fallback_frame_unwind;
 }
 
 /* Stub frames, used for all kinds of call stubs.  */
@@ -1942,6 +2099,7 @@ hppa_stub_frame_unwind_cache (struct frame_info *next_frame,
 {
   struct gdbarch *gdbarch = get_frame_arch (next_frame);
   struct hppa_stub_unwind_cache *info;
+  struct unwind_table_entry *u;
 
   if (*this_cache)
     return *this_cache;
@@ -1950,9 +2108,26 @@ hppa_stub_frame_unwind_cache (struct frame_info *next_frame,
   *this_cache = info;
   info->saved_regs = trad_frame_alloc_saved_regs (next_frame);
 
-  info->saved_regs[PCOQ_HEAD_REGNUM].realreg = RP_REGNUM;
   info->base = frame_unwind_register_unsigned (next_frame, HPPA_SP_REGNUM);
 
+  if (gdbarch_osabi (gdbarch) == GDB_OSABI_HPUX_SOM)
+    {
+      /* HPUX uses export stubs in function calls; the export stub clobbers
+         the return value of the caller, and, later restores it from the
+        stack.  */
+      u = find_unwind_entry (frame_pc_unwind (next_frame));
+
+      if (u && u->stub_unwind.stub_type == EXPORT)
+       {
+          info->saved_regs[HPPA_PCOQ_HEAD_REGNUM].addr = info->base - 24;
+
+         return info;
+       }
+    }
+
+  /* By default we assume that stubs do not change the rp.  */
+  info->saved_regs[HPPA_PCOQ_HEAD_REGNUM].realreg = HPPA_RP_REGNUM;
+
   return info;
 }
 
@@ -1971,23 +2146,12 @@ hppa_stub_frame_prev_register (struct frame_info *next_frame,
                               void **this_prologue_cache,
                               int regnum, int *optimizedp,
                               enum lval_type *lvalp, CORE_ADDR *addrp,
-                              int *realnump, void *bufferp)
+                              int *realnump, void *valuep)
 {
   struct hppa_stub_unwind_cache *info
     = hppa_stub_frame_unwind_cache (next_frame, this_prologue_cache);
-  int pcoqt = (regnum == PCOQ_TAIL_REGNUM);
-  struct gdbarch *gdbarch = get_frame_arch (next_frame);
-  int regsize = register_size (gdbarch, PCOQ_HEAD_REGNUM);
-
-  if (pcoqt)
-    regnum = PCOQ_HEAD_REGNUM;
-
-  trad_frame_prev_register (next_frame, info->saved_regs, regnum,
-                            optimizedp, lvalp, addrp, realnump, bufferp);
-
-  if (pcoqt)
-    store_unsigned_integer (bufferp, regsize, 
-                           extract_unsigned_integer (bufferp, regsize) + 4);
+  hppa_frame_prev_register_helper (next_frame, info->saved_regs, regnum,
+                                  optimizedp, lvalp, addrp, realnump, valuep);
 }
 
 static const struct frame_unwind hppa_stub_frame_unwind = {
@@ -2000,8 +2164,12 @@ static const struct frame_unwind *
 hppa_stub_unwind_sniffer (struct frame_info *next_frame)
 {
   CORE_ADDR pc = frame_pc_unwind (next_frame);
+  struct gdbarch *gdbarch = get_frame_arch (next_frame);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
 
-  if (IN_SOLIB_CALL_TRAMPOLINE (pc, NULL)
+  if (pc == 0
+      || (tdep->in_solib_call_trampoline != NULL
+         && tdep->in_solib_call_trampoline (pc, NULL))
       || IN_SOLIB_RETURN_TRAMPOLINE (pc, NULL))
     return &hppa_stub_frame_unwind;
   return NULL;
@@ -2018,7 +2186,7 @@ hppa_unwind_dummy_id (struct gdbarch *gdbarch, struct frame_info *next_frame)
 static CORE_ADDR
 hppa_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
 {
-  return frame_unwind_register_signed (next_frame, PCOQ_HEAD_REGNUM) & ~3;
+  return frame_unwind_register_signed (next_frame, HPPA_PCOQ_HEAD_REGNUM) & ~3;
 }
 
 /* Instead of this nasty cast, add a method pvoid() that prints out a
@@ -2057,9 +2225,11 @@ unwind_command (char *exp, int from_tty)
 
   printf_unfiltered ("\tregion_start = ");
   print_address (u->region_start, gdb_stdout);
+  gdb_flush (gdb_stdout);
 
   printf_unfiltered ("\n\tregion_end = ");
   print_address (u->region_end, gdb_stdout);
+  gdb_flush (gdb_stdout);
 
 #define pif(FLD) if (u->FLD) printf_unfiltered (" "#FLD);
 
@@ -2094,30 +2264,6 @@ unwind_command (char *exp, int from_tty)
   pin (Total_frame_size);
 }
 
-void
-hppa_skip_permanent_breakpoint (void)
-{
-  /* To step over a breakpoint instruction on the PA takes some
-     fiddling with the instruction address queue.
-
-     When we stop at a breakpoint, the IA queue front (the instruction
-     we're executing now) points at the breakpoint instruction, and
-     the IA queue back (the next instruction to execute) points to
-     whatever instruction we would execute after the breakpoint, if it
-     were an ordinary instruction.  This is the case even if the
-     breakpoint is in the delay slot of a branch instruction.
-
-     Clearly, to step past the breakpoint, we need to set the queue
-     front to the back.  But what do we put in the back?  What
-     instruction comes after that one?  Because of the branch delay
-     slot, the next insn is always at the back + 4.  */
-  write_register (PCOQ_HEAD_REGNUM, read_register (PCOQ_TAIL_REGNUM));
-  write_register (PCSQ_HEAD_REGNUM, read_register (PCSQ_TAIL_REGNUM));
-
-  write_register (PCOQ_TAIL_REGNUM, read_register (PCOQ_TAIL_REGNUM) + 4);
-  /* We can leave the tail's space the same, since there's no jump.  */
-}
-
 int
 hppa_pc_requires_run_before_use (CORE_ADDR pc)
 {
@@ -2152,8 +2298,8 @@ hppa_instruction_nullified (void)
   /* brobecker 2002/11/07: Couldn't we use a ULONGEST here? It would
      avoid the type cast.  I'm leaving it as is for now as I'm doing
      semi-mechanical multiarching-related changes.  */
-  const int ipsw = (int) read_register (IPSW_REGNUM);
-  const int flags = (int) read_register (FLAGS_REGNUM);
+  const int ipsw = (int) read_register (HPPA_IPSW_REGNUM);
+  const int flags = (int) read_register (HPPA_FLAGS_REGNUM);
 
   return ((ipsw & 0x00200000) && !(flags & 0x2));
 }
@@ -2164,7 +2310,7 @@ hppa_instruction_nullified (void)
 static struct type *
 hppa32_register_type (struct gdbarch *gdbarch, int reg_nr)
 {
-   if (reg_nr < FP4_REGNUM)
+   if (reg_nr < HPPA_FP4_REGNUM)
      return builtin_type_uint32;
    else
      return builtin_type_ieee_single_big;
@@ -2176,7 +2322,7 @@ hppa32_register_type (struct gdbarch *gdbarch, int reg_nr)
 static struct type *
 hppa64_register_type (struct gdbarch *gdbarch, int reg_nr)
 {
-   if (reg_nr < FP4_REGNUM)
+   if (reg_nr < HPPA_FP4_REGNUM)
      return builtin_type_uint64;
    else
      return builtin_type_ieee_double_big;
@@ -2189,9 +2335,9 @@ static int
 hppa_cannot_store_register (int regnum)
 {
   return (regnum == 0
-          || regnum == PCSQ_HEAD_REGNUM
-          || (regnum >= PCSQ_TAIL_REGNUM && regnum < IPSW_REGNUM)
-          || (regnum > IPSW_REGNUM && regnum < FP4_REGNUM));
+          || regnum == HPPA_PCSQ_HEAD_REGNUM
+          || (regnum >= HPPA_PCSQ_TAIL_REGNUM && regnum < HPPA_IPSW_REGNUM)
+          || (regnum > HPPA_IPSW_REGNUM && regnum < HPPA_FP4_REGNUM));
 
 }
 
@@ -2209,12 +2355,12 @@ hppa_smash_text_address (CORE_ADDR addr)
 }
 
 /* Get the ith function argument for the current function.  */
-CORE_ADDR
+static CORE_ADDR
 hppa_fetch_pointer_argument (struct frame_info *frame, int argi, 
                             struct type *type)
 {
   CORE_ADDR addr;
-  get_frame_register (frame, R0_REGNUM + 26 - argi, &addr);
+  get_frame_register (frame, HPPA_R0_REGNUM + 26 - argi, &addr);
   return addr;
 }
 
@@ -2225,11 +2371,51 @@ hppa_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
     ULONGEST tmp;
 
     regcache_raw_read_unsigned (regcache, regnum, &tmp);
-    if (regnum == PCOQ_HEAD_REGNUM || regnum == PCOQ_TAIL_REGNUM)
+    if (regnum == HPPA_PCOQ_HEAD_REGNUM || regnum == HPPA_PCOQ_TAIL_REGNUM)
       tmp &= ~0x3;
     store_unsigned_integer (buf, sizeof(tmp), tmp);
 }
 
+static CORE_ADDR
+hppa_find_global_pointer (struct value *function)
+{
+  return 0;
+}
+
+void
+hppa_frame_prev_register_helper (struct frame_info *next_frame,
+                                struct trad_frame_saved_reg saved_regs[],
+                                int regnum, int *optimizedp,
+                                enum lval_type *lvalp, CORE_ADDR *addrp,
+                                int *realnump, void *valuep)
+{
+  if (regnum == HPPA_PCOQ_TAIL_REGNUM)
+    {
+      if (valuep)
+       {
+         CORE_ADDR pc;
+
+         trad_frame_get_prev_register (next_frame, saved_regs,
+                                       HPPA_PCOQ_HEAD_REGNUM, optimizedp,
+                                       lvalp, addrp, realnump, valuep);
+
+         pc = extract_unsigned_integer (valuep, 4);
+         store_unsigned_integer (valuep, 4, pc + 4);
+       }
+
+      /* It's a computed value.  */
+      *optimizedp = 0;
+      *lvalp = not_lval;
+      *addrp = 0;
+      *realnump = -1;
+      return;
+    }
+
+  trad_frame_get_prev_register (next_frame, saved_regs, regnum,
+                               optimizedp, lvalp, addrp, realnump, valuep);
+}
+\f
+
 /* Here is a table of C type sizes on hppa with various compiles
    and options.  I measured this on PA 9000/800 with HP-UX 11.11
    and these compilers:
@@ -2297,6 +2483,8 @@ hppa_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   else
     tdep->bytes_per_address = 4;
 
+  tdep->find_global_pointer = hppa_find_global_pointer;
+
   /* Some parts of the gdbarch vector depend on whether we are running
      on a 32 bits or 64 bits target.  */
   switch (tdep->bytes_per_address)
@@ -2332,6 +2520,7 @@ hppa_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   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_cannot_fetch_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);
@@ -2355,6 +2544,8 @@ hppa_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
     case 4:
       set_gdbarch_push_dummy_call (gdbarch, hppa32_push_dummy_call);
       set_gdbarch_frame_align (gdbarch, hppa32_frame_align);
+      set_gdbarch_convert_from_func_ptr_addr
+        (gdbarch, hppa32_convert_from_func_ptr_addr);
       break;
     case 8:
       set_gdbarch_push_dummy_call (gdbarch, hppa64_push_dummy_call);
@@ -2384,13 +2575,13 @@ hppa_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_unwind_dummy_id (gdbarch, hppa_unwind_dummy_id);
   set_gdbarch_unwind_pc (gdbarch, hppa_unwind_pc);
 
+  /* Hook in ABI-specific overrides, if they have been registered.  */
+  gdbarch_init_osabi (info, gdbarch);
+
   /* Hook in the default unwinders.  */
   frame_unwind_append_sniffer (gdbarch, hppa_stub_unwind_sniffer);
   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);
+  frame_unwind_append_sniffer (gdbarch, hppa_fallback_unwind_sniffer);
 
   return gdbarch;
 }
@@ -2452,8 +2643,11 @@ be no argument or the argument must be a depth.\n"), NULL);
 be no argument or the argument must be a depth.\n"), NULL);
 
   /* Debug this files internals. */
-  add_show_from_set (add_set_cmd ("hppa", class_maintenance, var_zinteger,
-                                 &hppa_debug, "Set hppa debugging.\n\
-When non-zero, hppa specific debugging is enabled.", &setdebuglist), &showdebuglist);
+  add_setshow_boolean_cmd ("hppa", class_maintenance, &hppa_debug, "\
+Set whether hppa target specific debugging information should be displayed.", "\
+Show whether hppa target specific debugging information is displayed.", "\
+This flag controls whether hppa target specific debugging information is\n\
+displayed.  This information is particularly useful for debugging frame\n\
+unwinding problems.", "hppa debug flag is %s.",
+                          NULL, NULL, &setdebuglist, &showdebuglist);
 }
-
This page took 0.037786 seconds and 4 git commands to generate.