add autom4te.cache to .cvsignore
[deliverable/binutils-gdb.git] / gdb / hppa-tdep.c
index a10437152640e057e85f346200eded4708596904..059704080f9f5e329a4ebeed6bcb60a7f59d0583 100644 (file)
@@ -1,7 +1,7 @@
 /* Target-dependent code for the HP PA-RISC architecture.
 
-   Copyright 1986, 1987, 1989, 1990, 1991, 1992, 1993, 1994, 1995,
-   1996, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+   Copyright (C) 1986, 1987, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996,
+   1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007
    Free Software Foundation, Inc.
 
    Contributed by the Center for Software Science at the
@@ -21,8 +21,8 @@
 
    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.  */
+   Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.  */
 
 #include "defs.h"
 #include "bfd.h"
@@ -280,7 +280,7 @@ internalize_unwinds (struct objfile *objfile, struct unwind_table_entry *table,
          table[i].Millicode = (tmp >> 30) & 0x1;
          table[i].Millicode_save_sr0 = (tmp >> 29) & 0x1;
          table[i].Region_description = (tmp >> 27) & 0x3;
-         table[i].reserved1 = (tmp >> 26) & 0x1;
+         table[i].reserved = (tmp >> 26) & 0x1;
          table[i].Entry_SR = (tmp >> 25) & 0x1;
          table[i].Entry_FR = (tmp >> 21) & 0xf;
          table[i].Entry_GR = (tmp >> 16) & 0x1f;
@@ -290,23 +290,23 @@ internalize_unwinds (struct objfile *objfile, struct unwind_table_entry *table,
          table[i].Frame_Extension_Millicode = (tmp >> 12) & 0x1;
          table[i].Stack_Overflow_Check = (tmp >> 11) & 0x1;
          table[i].Two_Instruction_SP_Increment = (tmp >> 10) & 0x1;
-         table[i].Ada_Region = (tmp >> 9) & 0x1;
+         table[i].sr4export = (tmp >> 9) & 0x1;
          table[i].cxx_info = (tmp >> 8) & 0x1;
          table[i].cxx_try_catch = (tmp >> 7) & 0x1;
          table[i].sched_entry_seq = (tmp >> 6) & 0x1;
-         table[i].reserved2 = (tmp >> 5) & 0x1;
+         table[i].reserved1 = (tmp >> 5) & 0x1;
          table[i].Save_SP = (tmp >> 4) & 0x1;
          table[i].Save_RP = (tmp >> 3) & 0x1;
          table[i].Save_MRP_in_frame = (tmp >> 2) & 0x1;
-         table[i].extn_ptr_defined = (tmp >> 1) & 0x1;
+         table[i].save_r19 = (tmp >> 1) & 0x1;
          table[i].Cleanup_defined = tmp & 0x1;
          tmp = bfd_get_32 (objfile->obfd, (bfd_byte *) buf);
          buf += 4;
          table[i].MPE_XL_interrupt_marker = (tmp >> 31) & 0x1;
          table[i].HP_UX_interrupt_marker = (tmp >> 30) & 0x1;
          table[i].Large_frame = (tmp >> 29) & 0x1;
-         table[i].Pseudo_SP_Set = (tmp >> 28) & 0x1;
-         table[i].reserved4 = (tmp >> 27) & 0x1;
+         table[i].alloca_frame = (tmp >> 28) & 0x1;
+         table[i].reserved2 = (tmp >> 27) & 0x1;
          table[i].Total_frame_size = tmp & 0x7ffffff;
 
          /* Stub unwinds are handled elsewhere. */
@@ -549,7 +549,7 @@ hppa_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc)
   char buf[4];
   int off;
 
-  status = deprecated_read_memory_nobpt (pc, buf, 4);
+  status = read_memory_nobpt (pc, buf, 4);
   if (status != 0)
     return 0;
 
@@ -662,6 +662,21 @@ hppa64_register_name (int i)
     return names[i];
 }
 
+static int
+hppa64_dwarf_reg_to_regnum (int reg)
+{
+  /* r0-r31 and sar map one-to-one.  */
+  if (reg <= 32)
+    return reg;
+
+  /* fr4-fr31 are mapped from 72 in steps of 2.  */
+  if (reg >= 72 || reg < 72 + 28 * 2)
+    return HPPA64_FP4_REGNUM + (reg - 72) / 2;
+
+  error ("Invalid DWARF register num %d.", reg);
+  return -1;
+}
+
 /* This function pushes a stack frame with arguments as part of the
    inferior function calling mechanism.
 
@@ -882,6 +897,50 @@ hppa64_floating_p (const struct type *type)
   return 0;
 }
 
+/* If CODE points to a function entry address, try to look up the corresponding
+   function descriptor and return its address instead.  If CODE is not a
+   function entry address, then just return it unchanged.  */
+static CORE_ADDR
+hppa64_convert_code_addr_to_fptr (CORE_ADDR code)
+{
+  struct obj_section *sec, *opd;
+
+  sec = find_pc_section (code);
+
+  if (!sec)
+    return code;
+
+  /* If CODE is in a data section, assume it's already a fptr.  */
+  if (!(sec->the_bfd_section->flags & SEC_CODE))
+    return code;
+
+  ALL_OBJFILE_OSECTIONS (sec->objfile, opd)
+    {
+      if (strcmp (opd->the_bfd_section->name, ".opd") == 0)
+        break;
+    }
+
+  if (opd < sec->objfile->sections_end)
+    {
+      CORE_ADDR addr;
+
+      for (addr = opd->addr; addr < opd->endaddr; addr += 2 * 8)
+        {
+         ULONGEST opdaddr;
+         char tmp[8];
+
+         if (target_read_memory (addr, tmp, sizeof (tmp)))
+             break;
+         opdaddr = extract_unsigned_integer (tmp, sizeof (tmp));
+
+          if (opdaddr == code)
+           return addr - 16;
+       }
+    }
+
+  return code;
+}
+
 static CORE_ADDR
 hppa64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                        struct regcache *regcache, CORE_ADDR bp_addr,
@@ -902,6 +961,7 @@ hppa64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
       struct type *type = value_type (arg);
       int len = TYPE_LENGTH (type);
       const bfd_byte *valbuf;
+      bfd_byte fptrbuf[8];
       int regnum;
 
       /* "Each parameter begins on a 64-bit (8-byte) boundary."  */
@@ -977,10 +1037,26 @@ hppa64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
            }
        }
 
+      /* If we are passing a function pointer, make sure we pass a function
+         descriptor instead of the function entry address.  */
+      if (TYPE_CODE (type) == TYPE_CODE_PTR
+          && TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_FUNC)
+        {
+         ULONGEST codeptr, fptr;
+
+         codeptr = unpack_long (type, value_contents (arg));
+         fptr = hppa64_convert_code_addr_to_fptr (codeptr);
+         store_unsigned_integer (fptrbuf, TYPE_LENGTH (type), fptr);
+         valbuf = fptrbuf;
+       }
+      else
+        {
+          valbuf = value_contents (arg);
+       }
+
       /* Always store the argument in memory.  */
-      write_memory (sp + offset, value_contents (arg), len);
+      write_memory (sp + offset, valbuf, len);
 
-      valbuf = value_contents (arg);
       regnum = HPPA_ARG0_REGNUM - offset / 8;
       while (regnum > HPPA_ARG0_REGNUM - 8 && len > 0)
        {
@@ -1479,7 +1555,7 @@ restart:
       old_save_sp = save_sp;
       old_stack_remaining = stack_remaining;
 
-      status = deprecated_read_memory_nobpt (pc, buf, 4);
+      status = read_memory_nobpt (pc, buf, 4);
       inst = extract_unsigned_integer (buf, 4);
 
       /* Yow! */
@@ -1491,7 +1567,7 @@ restart:
 
       /* There are limited ways to store the return pointer into the
         stack.  */
-      if (inst == 0x6bc23fd9 || inst == 0x0fc212c1)
+      if (inst == 0x6bc23fd9 || inst == 0x0fc212c1 || inst == 0x73c23fe1)
        save_rp = 0;
 
       /* These are the only ways we save SP into the stack.  At this time
@@ -1528,7 +1604,7 @@ restart:
          while (reg_num >= (TARGET_PTR_BIT == 64 ? 19 : 23) && reg_num <= 26)
            {
              pc += 4;
-             status = deprecated_read_memory_nobpt (pc, buf, 4);
+             status = read_memory_nobpt (pc, buf, 4);
              inst = extract_unsigned_integer (buf, 4);
              if (status != 0)
                return pc;
@@ -1541,7 +1617,7 @@ restart:
       reg_num = inst_saves_fr (inst);
       save_fr &= ~(1 << reg_num);
 
-      status = deprecated_read_memory_nobpt (pc + 4, buf, 4);
+      status = read_memory_nobpt (pc + 4, buf, 4);
       next_inst = extract_unsigned_integer (buf, 4);
 
       /* Yow! */
@@ -1568,13 +1644,13 @@ restart:
          while (reg_num >= 4 && reg_num <= (TARGET_PTR_BIT == 64 ? 11 : 7))
            {
              pc += 8;
-             status = deprecated_read_memory_nobpt (pc, buf, 4);
+             status = read_memory_nobpt (pc, buf, 4);
              inst = extract_unsigned_integer (buf, 4);
              if (status != 0)
                return pc;
              if ((inst & 0xfc000000) != 0x34000000)
                break;
-             status = deprecated_read_memory_nobpt (pc + 4, buf, 4);
+             status = read_memory_nobpt (pc + 4, buf, 4);
              next_inst = extract_unsigned_integer (buf, 4);
              if (status != 0)
                return pc;
@@ -1706,6 +1782,17 @@ hppa_skip_prologue (CORE_ADDR pc)
     return (skip_prologue_hard_way (pc, 1));
 }
 
+/* Return an unwind entry that falls within the frame's code block.  */
+static struct unwind_table_entry *
+hppa_find_unwind_entry_in_block (struct frame_info *f)
+{
+  CORE_ADDR pc;
+
+  pc = frame_unwind_address_in_block (f);
+  pc = gdbarch_addr_bits_remove (get_frame_arch (f), pc);
+  return find_unwind_entry (pc);
+}
+
 struct hppa_frame_cache
 {
   CORE_ADDR base;
@@ -1741,7 +1828,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_pc_unwind (next_frame));
+  u = hppa_find_unwind_entry_in_block (next_frame);
   if (!u)
     {
       if (hppa_debug)
@@ -1781,7 +1868,7 @@ hppa_frame_cache (struct frame_info *next_frame, void **this_cache)
      GCC code.  */
   {
     int final_iteration = 0;
-    CORE_ADDR pc, end_pc;
+    CORE_ADDR pc, start_pc, end_pc;
     int looking_for_sp = u->Save_SP;
     int looking_for_rp = u->Save_RP;
     int fp_loc = -1;
@@ -1801,9 +1888,19 @@ hppa_frame_cache (struct frame_info *next_frame, void **this_cache)
     /* 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.  */
+       function (or 0).  We can do better than that by using unwind records.  
+       This only works if the Region_description of the unwind record
+       indicates that it includes the entry point of the function.  
+       HP compilers sometimes generate unwind records for regions that
+       do not include the entry or exit point of a function.  GNU tools
+       do not do this.  */
+
+    if ((u->Region_description & 0x2) == 0)
+      start_pc = u->region_start;
+    else
+      start_pc = frame_func_unwind (next_frame);
 
-    prologue_end = skip_prologue_hard_way (u->region_start, 0);
+    prologue_end = skip_prologue_hard_way (start_pc, 0);
     end_pc = frame_pc_unwind (next_frame);
 
     if (prologue_end != 0 && end_pc > prologue_end)
@@ -1811,7 +1908,7 @@ hppa_frame_cache (struct frame_info *next_frame, void **this_cache)
 
     frame_size = 0;
 
-    for (pc = u->region_start;
+    for (pc = start_pc;
         ((saved_gr_mask || saved_fr_mask
           || looking_for_sp || looking_for_rp
           || frame_size < (u->Total_frame_size << 3))
@@ -1846,7 +1943,8 @@ hppa_frame_cache (struct frame_info *next_frame, void **this_cache)
            looking_for_rp = 0;
            cache->saved_regs[HPPA_RP_REGNUM].addr = -24;
          }
-       else if (inst == 0x0fc212c1) /* std rp,-0x10(sr0,sp) */
+       else if (inst == 0x0fc212c1 
+                || inst == 0x73c23fe1) /* std rp,-0x10(sr0,sp) */
          {
            looking_for_rp = 0;
            cache->saved_regs[HPPA_RP_REGNUM].addr = -16;
@@ -1977,14 +2075,17 @@ hppa_frame_cache (struct frame_info *next_frame, void **this_cache)
        instead of Save_SP.  */
  
      fp = frame_unwind_register_unsigned (next_frame, HPPA_FP_REGNUM);
+
+     if (u->alloca_frame)
+       fp -= u->Total_frame_size << 3;
  
      if (frame_pc_unwind (next_frame) >= prologue_end
-         && u->Save_SP && fp != 0)
+         && (u->Save_SP || u->alloca_frame) && fp != 0)
       {
        cache->base = fp;
  
        if (hppa_debug)
-         fprintf_unfiltered (gdb_stdlog, " (base=0x%s) [frame pointer] }",
+         fprintf_unfiltered (gdb_stdlog, " (base=0x%s) [frame pointer]",
            paddr_nz (cache->base));
       }
      else if (u->Save_SP 
@@ -1996,7 +2097,7 @@ hppa_frame_cache (struct frame_info *next_frame, void **this_cache)
             cache->base = read_memory_integer (this_sp, TARGET_PTR_BIT / 8);
 
            if (hppa_debug)
-             fprintf_unfiltered (gdb_stdlog, " (base=0x%s) [saved] }",
+             fprintf_unfiltered (gdb_stdlog, " (base=0x%s) [saved]",
                                  paddr_nz (cache->base));
       }
     else
@@ -2005,7 +2106,7 @@ hppa_frame_cache (struct frame_info *next_frame, void **this_cache)
           the SP back.  */
         cache->base = this_sp - frame_size;
        if (hppa_debug)
-         fprintf_unfiltered (gdb_stdlog, " (base=0x%s) [unwind adjust] } ",
+         fprintf_unfiltered (gdb_stdlog, " (base=0x%s) [unwind adjust]",
                              paddr_nz (cache->base));
 
       }
@@ -2017,21 +2118,34 @@ hppa_frame_cache (struct frame_info *next_frame, void **this_cache)
   if (u->Millicode)
     {
       if (trad_frame_addr_p (cache->saved_regs, 31))
-        cache->saved_regs[HPPA_PCOQ_HEAD_REGNUM] = cache->saved_regs[31];
+        {
+          cache->saved_regs[HPPA_PCOQ_HEAD_REGNUM] = cache->saved_regs[31];
+         if (hppa_debug)
+           fprintf_unfiltered (gdb_stdlog, " (pc=r31) [stack] } ");
+        }
       else
        {
          ULONGEST r31 = frame_unwind_register_unsigned (next_frame, 31);
          trad_frame_set_value (cache->saved_regs, HPPA_PCOQ_HEAD_REGNUM, r31);
+         if (hppa_debug)
+           fprintf_unfiltered (gdb_stdlog, " (pc=r31) [frame] } ");
         }
     }
   else
     {
       if (trad_frame_addr_p (cache->saved_regs, HPPA_RP_REGNUM))
-        cache->saved_regs[HPPA_PCOQ_HEAD_REGNUM] = cache->saved_regs[HPPA_RP_REGNUM];
+        {
+          cache->saved_regs[HPPA_PCOQ_HEAD_REGNUM] = 
+           cache->saved_regs[HPPA_RP_REGNUM];
+         if (hppa_debug)
+           fprintf_unfiltered (gdb_stdlog, " (pc=rp) [stack] } ");
+        }
       else
        {
          ULONGEST rp = frame_unwind_register_unsigned (next_frame, HPPA_RP_REGNUM);
          trad_frame_set_value (cache->saved_regs, HPPA_PCOQ_HEAD_REGNUM, rp);
+         if (hppa_debug)
+           fprintf_unfiltered (gdb_stdlog, " (pc=rp) [frame] } ");
        }
     }
 
@@ -2094,7 +2208,7 @@ hppa_frame_this_id (struct frame_info *next_frame, void **this_cache,
   struct unwind_table_entry *u;
 
   info = hppa_frame_cache (next_frame, this_cache);
-  u = find_unwind_entry (pc);
+  u = hppa_find_unwind_entry_in_block (next_frame);
 
   (*this_id) = frame_id_build (info->base, u->region_start);
 }
@@ -2121,9 +2235,7 @@ static const struct frame_unwind hppa_frame_unwind =
 static const struct frame_unwind *
 hppa_frame_unwind_sniffer (struct frame_info *next_frame)
 {
-  CORE_ADDR pc = frame_pc_unwind (next_frame);
-
-  if (find_unwind_entry (pc))
+  if (hppa_find_unwind_entry_in_block (next_frame))
     return &hppa_frame_unwind;
 
   return NULL;
@@ -2174,7 +2286,8 @@ hppa_fallback_frame_cache (struct frame_info *next_frame, void **this_cache)
              cache->saved_regs[HPPA_RP_REGNUM].addr = -20;
              found_rp = 1;
            }
-         else if (insn == 0x0fc212c1) /* std rp,-0x10(sr0,sp) */
+         else if (insn == 0x0fc212c1
+                  || insn == 0x73c23fe1) /* std rp,-0x10(sr0,sp) */
            {
              cache->saved_regs[HPPA_RP_REGNUM].addr = -16;
              found_rp = 1;
@@ -2436,15 +2549,19 @@ unwind_command (char *exp, int from_tty)
   pif (Frame_Extension_Millicode);
   pif (Stack_Overflow_Check);
   pif (Two_Instruction_SP_Increment);
-  pif (Ada_Region);
+  pif (sr4export);
+  pif (cxx_info);
+  pif (cxx_try_catch);
+  pif (sched_entry_seq);
   pif (Save_SP);
   pif (Save_RP);
   pif (Save_MRP_in_frame);
-  pif (extn_ptr_defined);
+  pif (save_r19);
   pif (Cleanup_defined);
   pif (MPE_XL_interrupt_marker);
   pif (HP_UX_interrupt_marker);
   pif (Large_frame);
+  pif (alloca_frame);
 
   putchar_unfiltered ('\n');
 
@@ -2518,7 +2635,7 @@ hppa32_register_type (struct gdbarch *gdbarch, int regnum)
    if (regnum < HPPA_FP4_REGNUM)
      return builtin_type_uint32;
    else
-     return builtin_type_ieee_single_big;
+     return builtin_type_ieee_single;
 }
 
 static struct type *
@@ -2527,7 +2644,7 @@ hppa64_register_type (struct gdbarch *gdbarch, int regnum)
    if (regnum < HPPA64_FP4_REGNUM)
      return builtin_type_uint64;
    else
-     return builtin_type_ieee_double_big;
+     return builtin_type_ieee_double;
 }
 
 /* Return non-zero if REGNUM is not a register available to the user
@@ -2646,6 +2763,223 @@ hppa_frame_prev_register_helper (struct frame_info *next_frame,
 }
 \f
 
+/* An instruction to match.  */
+struct insn_pattern
+{
+  unsigned int data;            /* See if it matches this....  */
+  unsigned int mask;            /* ... with this mask.  */
+};
+
+/* See bfd/elf32-hppa.c */
+static struct insn_pattern hppa_long_branch_stub[] = {
+  /* ldil LR'xxx,%r1 */
+  { 0x20200000, 0xffe00000 },
+  /* be,n RR'xxx(%sr4,%r1) */
+  { 0xe0202002, 0xffe02002 }, 
+  { 0, 0 }
+};
+
+static struct insn_pattern hppa_long_branch_pic_stub[] = {
+  /* b,l .+8, %r1 */
+  { 0xe8200000, 0xffe00000 },
+  /* addil LR'xxx - ($PIC_pcrel$0 - 4), %r1 */
+  { 0x28200000, 0xffe00000 },
+  /* be,n RR'xxxx - ($PIC_pcrel$0 - 8)(%sr4, %r1) */
+  { 0xe0202002, 0xffe02002 }, 
+  { 0, 0 }
+};
+
+static struct insn_pattern hppa_import_stub[] = {
+  /* addil LR'xxx, %dp */
+  { 0x2b600000, 0xffe00000 },
+  /* ldw RR'xxx(%r1), %r21 */
+  { 0x48350000, 0xffffb000 },
+  /* bv %r0(%r21) */
+  { 0xeaa0c000, 0xffffffff },
+  /* ldw RR'xxx+4(%r1), %r19 */
+  { 0x48330000, 0xffffb000 },
+  { 0, 0 }
+};
+
+static struct insn_pattern hppa_import_pic_stub[] = {
+  /* addil LR'xxx,%r19 */
+  { 0x2a600000, 0xffe00000 },
+  /* ldw RR'xxx(%r1),%r21 */
+  { 0x48350000, 0xffffb000 },
+  /* bv %r0(%r21) */
+  { 0xeaa0c000, 0xffffffff },
+  /* ldw RR'xxx+4(%r1),%r19 */
+  { 0x48330000, 0xffffb000 },
+  { 0, 0 },
+};
+
+static struct insn_pattern hppa_plt_stub[] = {
+  /* b,l 1b, %r20 - 1b is 3 insns before here */
+  { 0xea9f1fdd, 0xffffffff },
+  /* depi 0,31,2,%r20 */
+  { 0xd6801c1e, 0xffffffff },
+  { 0, 0 }
+};
+
+static struct insn_pattern hppa_sigtramp[] = {
+  /* ldi 0, %r25 or ldi 1, %r25 */
+  { 0x34190000, 0xfffffffd },
+  /* ldi __NR_rt_sigreturn, %r20 */
+  { 0x3414015a, 0xffffffff },
+  /* be,l 0x100(%sr2, %r0), %sr0, %r31 */
+  { 0xe4008200, 0xffffffff },
+  /* nop */
+  { 0x08000240, 0xffffffff },
+  { 0, 0 }
+};
+
+/* Maximum number of instructions on the patterns above.  */
+#define HPPA_MAX_INSN_PATTERN_LEN      4
+
+/* Return non-zero if the instructions at PC match the series
+   described in PATTERN, or zero otherwise.  PATTERN is an array of
+   'struct insn_pattern' objects, terminated by an entry whose mask is
+   zero.
+
+   When the match is successful, fill INSN[i] with what PATTERN[i]
+   matched.  */
+
+static int
+hppa_match_insns (CORE_ADDR pc, struct insn_pattern *pattern,
+                 unsigned int *insn)
+{
+  CORE_ADDR npc = pc;
+  int i;
+
+  for (i = 0; pattern[i].mask; i++)
+    {
+      gdb_byte buf[HPPA_INSN_SIZE];
+
+      read_memory_nobpt (npc, buf, HPPA_INSN_SIZE);
+      insn[i] = extract_unsigned_integer (buf, HPPA_INSN_SIZE);
+      if ((insn[i] & pattern[i].mask) == pattern[i].data)
+        npc += 4;
+      else
+        return 0;
+    }
+
+  return 1;
+}
+
+/* This relaxed version of the insstruction matcher allows us to match
+   from somewhere inside the pattern, by looking backwards in the
+   instruction scheme.  */
+
+static int
+hppa_match_insns_relaxed (CORE_ADDR pc, struct insn_pattern *pattern,
+                         unsigned int *insn)
+{
+  int offset, len = 0;
+
+  while (pattern[len].mask)
+    len++;
+
+  for (offset = 0; offset < len; offset++)
+    if (hppa_match_insns (pc - offset * HPPA_INSN_SIZE, pattern, insn))
+      return 1;
+
+  return 0;
+}
+
+static int
+hppa_in_dyncall (CORE_ADDR pc)
+{
+  struct unwind_table_entry *u;
+
+  u = find_unwind_entry (hppa_symbol_address ("$$dyncall"));
+  if (!u)
+    return 0;
+
+  return (pc >= u->region_start && pc <= u->region_end);
+}
+
+int
+hppa_in_solib_call_trampoline (CORE_ADDR pc, char *name)
+{
+  unsigned int insn[HPPA_MAX_INSN_PATTERN_LEN];
+  struct unwind_table_entry *u;
+
+  if (in_plt_section (pc, name) || hppa_in_dyncall (pc))
+    return 1;
+
+  /* The GNU toolchain produces linker stubs without unwind
+     information.  Since the pattern matching for linker stubs can be
+     quite slow, so bail out if we do have an unwind entry.  */
+
+  u = find_unwind_entry (pc);
+  if (u != NULL)
+    return 0;
+
+  return (hppa_match_insns_relaxed (pc, hppa_import_stub, insn)
+         || hppa_match_insns_relaxed (pc, hppa_import_pic_stub, insn)
+         || hppa_match_insns_relaxed (pc, hppa_long_branch_stub, insn)
+         || hppa_match_insns_relaxed (pc, hppa_long_branch_pic_stub, insn));
+}
+
+/* This code skips several kind of "trampolines" used on PA-RISC
+   systems: $$dyncall, import stubs and PLT stubs.  */
+
+CORE_ADDR
+hppa_skip_trampoline_code (CORE_ADDR pc)
+{
+  unsigned int insn[HPPA_MAX_INSN_PATTERN_LEN];
+  int dp_rel;
+
+  /* $$dyncall handles both PLABELs and direct addresses.  */
+  if (hppa_in_dyncall (pc))
+    {
+      pc = read_register (HPPA_R0_REGNUM + 22);
+
+      /* PLABELs have bit 30 set; if it's a PLABEL, then dereference it.  */
+      if (pc & 0x2)
+       pc = read_memory_typed_address (pc & ~0x3, builtin_type_void_func_ptr);
+
+      return pc;
+    }
+
+  dp_rel = hppa_match_insns (pc, hppa_import_stub, insn);
+  if (dp_rel || hppa_match_insns (pc, hppa_import_pic_stub, insn))
+    {
+      /* Extract the target address from the addil/ldw sequence.  */
+      pc = hppa_extract_21 (insn[0]) + hppa_extract_14 (insn[1]);
+
+      if (dp_rel)
+        pc += read_register (HPPA_DP_REGNUM);
+      else
+        pc += read_register (HPPA_R0_REGNUM + 19);
+
+      /* fallthrough */
+    }
+
+  if (in_plt_section (pc, NULL))
+    {
+      pc = read_memory_typed_address (pc, builtin_type_void_func_ptr);
+
+      /* If the PLT slot has not yet been resolved, the target will be
+         the PLT stub.  */
+      if (in_plt_section (pc, NULL))
+       {
+         /* Sanity check: are we pointing to the PLT stub?  */
+         if (!hppa_match_insns (pc, hppa_plt_stub, insn))
+           {
+             warning (_("Cannot resolve PLT stub at 0x%s."), paddr_nz (pc));
+             return 0;
+           }
+
+         /* This should point to the fixup routine.  */
+         pc = read_memory_typed_address (pc + 8, builtin_type_void_func_ptr);
+       }
+    }
+
+  return pc;
+}
+\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:
@@ -2732,6 +3066,8 @@ hppa_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
         set_gdbarch_num_regs (gdbarch, hppa64_num_regs);
         set_gdbarch_register_name (gdbarch, hppa64_register_name);
         set_gdbarch_register_type (gdbarch, hppa64_register_type);
+        set_gdbarch_dwarf_reg_to_regnum (gdbarch, hppa64_dwarf_reg_to_regnum);
+        set_gdbarch_dwarf2_reg_to_regnum (gdbarch, hppa64_dwarf_reg_to_regnum);
        set_gdbarch_cannot_store_register (gdbarch,
                                           hppa64_cannot_store_register);
        set_gdbarch_cannot_fetch_register (gdbarch,
@@ -2749,7 +3085,7 @@ hppa_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
      and LP64, but might show differences some day.  */
   set_gdbarch_long_long_bit (gdbarch, 64);
   set_gdbarch_long_double_bit (gdbarch, 128);
-  set_gdbarch_long_double_format (gdbarch, &floatformat_ia64_quad_big);
+  set_gdbarch_long_double_format (gdbarch, floatformats_ia64_quad);
 
   /* The following gdbarch vector elements do not depend on the address
      size, or in any other gdbarch element previously set.  */
This page took 0.033601 seconds and 4 git commands to generate.