2004-02-22 Andrew Cagney <cagney@redhat.com>
[deliverable/binutils-gdb.git] / gdb / hppa-tdep.c
index 5cedfe74c4bb3e9b45801c3ebf1f64f618f936a4..21f86d5e006ecb52565ffd8304f09a03c956515d 100644 (file)
@@ -1,7 +1,8 @@
 /* Target-dependent code for the HP PA architecture, for GDB.
 
    Copyright 1986, 1987, 1989, 1990, 1991, 1992, 1993, 1994, 1995,
-   1996, 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+   1996, 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software
+   Foundation, Inc.
 
    Contributed by the Center for Software Science at the
    University of Utah (pa-gdb-bugs@cs.utah.edu).
 #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"
 
 #ifdef USG
 #include <sys/types.h>
 #include "target.h"
 #include "symfile.h"
 #include "objfiles.h"
+#include "hppa-tdep.h"
 
 /* Some local constants.  */
-static const int hppa_num_regs = 128;
+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)
+#define SR4EXPORT_LDO_OFFSET (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 int get_field (unsigned word, int from, int to);
+
 static int extract_5_load (unsigned int);
 
 static unsigned extract_5R_store (unsigned int);
 
 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);
@@ -107,9 +148,6 @@ static int restore_pc_queue (CORE_ADDR *);
 
 static int hppa_alignof (struct type *);
 
-/* To support multi-threading and stepping. */
-int hppa_prepare_to_proceed ();
-
 static int prologue_inst_adjust_sp (unsigned long);
 
 static int is_branch (unsigned long);
@@ -145,17 +183,23 @@ 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 hppa_stack_align (CORE_ADDR sp);
+CORE_ADDR hppa32_stack_align (CORE_ADDR sp);
+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 * hppa_register_virtual_type (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 hppa_extract_return_value (struct type *type, char *regbuf, char *valbuf);
-int hppa_use_struct_convention (int gcc_p, struct type *type);
-void hppa_store_return_value (struct type *type, char *valbuf);
-CORE_ADDR hppa_extract_struct_value_address (char *regbuf);
+void hppa32_extract_return_value (struct type *type, char *regbuf,
+                                  char *valbuf);
+void hppa64_extract_return_value (struct type *type, char *regbuf,
+                                  char *valbuf);
+int hppa32_use_struct_convention (int gcc_p, struct type *type);
+int hppa64_use_struct_convention (int gcc_p, struct type *type);
+void hppa32_store_return_value (struct type *type, char *valbuf);
+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);
@@ -163,7 +207,6 @@ 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);
-CORE_ADDR hppa_frame_locals_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);
@@ -198,11 +241,19 @@ extern int exception_catchpoints_are_fragile;
 /* Should call_function allocate stack space for a struct return?  */
 
 int
-hppa_use_struct_convention (int gcc_p, struct type *type)
+hppa32_use_struct_convention (int gcc_p, struct type *type)
 {
   return (TYPE_LENGTH (type) > 2 * DEPRECATED_REGISTER_SIZE);
 }
-\f
+
+/* Same as hppa32_use_struct_convention() for the PA64 ABI.  */
+
+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;
+}
 
 /* Routines to extract various sized constants out of hppa 
    instructions. */
@@ -224,6 +275,15 @@ low_sign_extend (unsigned val, unsigned bits)
   return (int) ((val & 0x1 ? (-1 << (bits - 1)) : 0) | val >> 1);
 }
 
+/* Extract the bits at positions between FROM and TO, using HP's numbering
+   (MSB = 0). */
+
+static int
+get_field (unsigned word, int from, int to)
+{
+  return ((word) >> (31 - (to)) & ((1 << ((to) - (from) + 1)) - 1));
+}
+
 /* extract the immediate field from a ld{bhw}s instruction */
 
 static int
@@ -275,15 +335,15 @@ extract_21 (unsigned word)
 
   word &= MASK_21;
   word <<= 11;
-  val = GET_FIELD (word, 20, 20);
+  val = get_field (word, 20, 20);
   val <<= 11;
-  val |= GET_FIELD (word, 9, 19);
+  val |= get_field (word, 9, 19);
   val <<= 2;
-  val |= GET_FIELD (word, 5, 6);
+  val |= get_field (word, 5, 6);
   val <<= 5;
-  val |= GET_FIELD (word, 0, 4);
+  val |= get_field (word, 0, 4);
   val <<= 2;
-  val |= GET_FIELD (word, 7, 8);
+  val |= get_field (word, 7, 8);
   return sign_extend (val, 21) << 11;
 }
 
@@ -296,15 +356,15 @@ deposit_21 (unsigned opnd, unsigned word)
 {
   unsigned val = 0;
 
-  val |= GET_FIELD (opnd, 11 + 14, 11 + 18);
+  val |= get_field (opnd, 11 + 14, 11 + 18);
   val <<= 2;
-  val |= GET_FIELD (opnd, 11 + 12, 11 + 13);
+  val |= get_field (opnd, 11 + 12, 11 + 13);
   val <<= 2;
-  val |= GET_FIELD (opnd, 11 + 19, 11 + 20);
+  val |= get_field (opnd, 11 + 19, 11 + 20);
   val <<= 11;
-  val |= GET_FIELD (opnd, 11 + 1, 11 + 11);
+  val |= get_field (opnd, 11 + 1, 11 + 11);
   val <<= 1;
-  val |= GET_FIELD (opnd, 11 + 0, 11 + 0);
+  val |= get_field (opnd, 11 + 0, 11 + 0);
   return word | val;
 }
 
@@ -314,9 +374,9 @@ deposit_21 (unsigned opnd, unsigned word)
 static int
 extract_17 (unsigned word)
 {
-  return sign_extend (GET_FIELD (word, 19, 28) |
-                     GET_FIELD (word, 29, 29) << 10 |
-                     GET_FIELD (word, 11, 15) << 11 |
+  return sign_extend (get_field (word, 19, 28) |
+                     get_field (word, 29, 29) << 10 |
+                     get_field (word, 11, 15) << 11 |
                      (word & 0x1) << 16, 17) << 2;
 }
 \f
@@ -456,7 +516,7 @@ read_unwind_info (struct objfile *objfile)
   obj_private_data_t *obj_private;
 
   text_offset = ANOFFSET (objfile->section_offsets, 0);
-  ui = (struct obj_unwind_info *) obstack_alloc (&objfile->psymbol_obstack,
+  ui = (struct obj_unwind_info *) obstack_alloc (&objfile->objfile_obstack,
                                           sizeof (struct obj_unwind_info));
 
   ui->table = NULL;
@@ -506,7 +566,7 @@ read_unwind_info (struct objfile *objfile)
 
   /* Allocate memory for the unwind table.  */
   ui->table = (struct unwind_table_entry *)
-    obstack_alloc (&objfile->psymbol_obstack, total_size);
+    obstack_alloc (&objfile->objfile_obstack, total_size);
   ui->last = total_entries - 1;
 
   /* Now read in each unwind section and internalize the standard unwind
@@ -569,7 +629,7 @@ read_unwind_info (struct objfile *objfile)
   if (objfile->obj_private == NULL)
     {
       obj_private = (obj_private_data_t *)
-       obstack_alloc (&objfile->psymbol_obstack,
+       obstack_alloc (&objfile->objfile_obstack,
                       sizeof (obj_private_data_t));
       obj_private->unwind_info = NULL;
       obj_private->so_info = NULL;
@@ -645,11 +705,93 @@ find_unwind_entry (CORE_ADDR pc)
 const unsigned char *
 hppa_breakpoint_from_pc (CORE_ADDR *pc, int *len)
 {
-  static const char breakpoint[] = {0x00, 0x01, 0x00, 0x04};
+  static const unsigned char breakpoint[] = {0x00, 0x01, 0x00, 0x04};
   (*len) = sizeof (breakpoint);
   return breakpoint;
 }
 
+/* Return the name of a register.  */
+
+const char *
+hppa32_register_name (int i)
+{
+  static char *names[] = {
+    "flags",  "r1",      "rp",     "r3",
+    "r4",     "r5",      "r6",     "r7",
+    "r8",     "r9",      "r10",    "r11",
+    "r12",    "r13",     "r14",    "r15",
+    "r16",    "r17",     "r18",    "r19",
+    "r20",    "r21",     "r22",    "r23",
+    "r24",    "r25",     "r26",    "dp",
+    "ret0",   "ret1",    "sp",     "r31",
+    "sar",    "pcoqh",   "pcsqh",  "pcoqt",
+    "pcsqt",  "eiem",    "iir",    "isr",
+    "ior",    "ipsw",    "goto",   "sr4",
+    "sr0",    "sr1",     "sr2",    "sr3",
+    "sr5",    "sr6",     "sr7",    "cr0",
+    "cr8",    "cr9",     "ccr",    "cr12",
+    "cr13",   "cr24",    "cr25",   "cr26",
+    "mpsfu_high","mpsfu_low","mpsfu_ovflo","pad",
+    "fpsr",    "fpe1",   "fpe2",   "fpe3",
+    "fpe4",   "fpe5",    "fpe6",   "fpe7",
+    "fr4",     "fr4R",   "fr5",    "fr5R",
+    "fr6",    "fr6R",    "fr7",    "fr7R",
+    "fr8",     "fr8R",   "fr9",    "fr9R",
+    "fr10",   "fr10R",   "fr11",   "fr11R",
+    "fr12",    "fr12R",  "fr13",   "fr13R",
+    "fr14",   "fr14R",   "fr15",   "fr15R",
+    "fr16",    "fr16R",  "fr17",   "fr17R",
+    "fr18",   "fr18R",   "fr19",   "fr19R",
+    "fr20",    "fr20R",  "fr21",   "fr21R",
+    "fr22",   "fr22R",   "fr23",   "fr23R",
+    "fr24",    "fr24R",  "fr25",   "fr25R",
+    "fr26",   "fr26R",   "fr27",   "fr27R",
+    "fr28",    "fr28R",  "fr29",   "fr29R",
+    "fr30",   "fr30R",   "fr31",   "fr31R"
+  };
+  if (i < 0 || i >= (sizeof (names) / sizeof (*names)))
+    return NULL;
+  else
+    return names[i];
+}
+
+const char *
+hppa64_register_name (int i)
+{
+  static char *names[] = {
+    "flags",  "r1",      "rp",     "r3",
+    "r4",     "r5",      "r6",     "r7",
+    "r8",     "r9",      "r10",    "r11",
+    "r12",    "r13",     "r14",    "r15",
+    "r16",    "r17",     "r18",    "r19",
+    "r20",    "r21",     "r22",    "r23",
+    "r24",    "r25",     "r26",    "dp",
+    "ret0",   "ret1",    "sp",     "r31",
+    "sar",    "pcoqh",   "pcsqh",  "pcoqt",
+    "pcsqt",  "eiem",    "iir",    "isr",
+    "ior",    "ipsw",    "goto",   "sr4",
+    "sr0",    "sr1",     "sr2",    "sr3",
+    "sr5",    "sr6",     "sr7",    "cr0",
+    "cr8",    "cr9",     "ccr",    "cr12",
+    "cr13",   "cr24",    "cr25",   "cr26",
+    "mpsfu_high","mpsfu_low","mpsfu_ovflo","pad",
+    "fpsr",    "fpe1",   "fpe2",   "fpe3",
+    "fr4",    "fr5",     "fr6",    "fr7",
+    "fr8",     "fr9",    "fr10",   "fr11",
+    "fr12",   "fr13",    "fr14",   "fr15",
+    "fr16",    "fr17",   "fr18",   "fr19",
+    "fr20",   "fr21",    "fr22",   "fr23",
+    "fr24",    "fr25",   "fr26",   "fr27",
+    "fr28",  "fr29",    "fr30",   "fr31"
+  };
+  if (i < 0 || i >= (sizeof (names) / sizeof (*names)))
+    return NULL;
+  else
+    return names[i];
+}
+
+
+
 /* Return the adjustment necessary to make for addresses on the stack
    as presented by hpread.c.
 
@@ -954,7 +1096,7 @@ hppa_frame_saved_pc (struct frame_info *frame)
        {
          CORE_ADDR *saved_regs;
          hppa_frame_init_saved_regs (get_next_frame (frame));
-         saved_regs = get_frame_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)
            {
@@ -994,7 +1136,7 @@ hppa_frame_saved_pc (struct frame_info *frame)
        {
          CORE_ADDR *saved_regs;
          hppa_frame_init_saved_regs (get_next_frame (frame));
-         saved_regs = get_frame_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)
            {
@@ -1268,7 +1410,7 @@ hppa_frame_chain (struct frame_info *frame)
             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 = get_frame_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.  */
@@ -1319,7 +1461,7 @@ hppa_frame_chain (struct frame_info *frame)
          if (tmp_frame != saved_regs_frame)
            {
              hppa_frame_init_saved_regs (tmp_frame);
-             saved_regs = get_frame_saved_regs (tmp_frame);
+             saved_regs = deprecated_get_frame_saved_regs (tmp_frame);
            }
 
          /* Abominable hack.  */
@@ -1357,7 +1499,7 @@ hppa_frame_chain (struct frame_info *frame)
       if (tmp_frame != saved_regs_frame)
        {
          hppa_frame_init_saved_regs (tmp_frame);
-         saved_regs = get_frame_saved_regs (tmp_frame);
+         saved_regs = deprecated_get_frame_saved_regs (tmp_frame);
        }
 
       /* Abominable hack.  See above.  */
@@ -1452,7 +1594,7 @@ void
 hppa_push_dummy_frame (void)
 {
   CORE_ADDR sp, pc, pcspace;
-  register int regnum;
+  int regnum;
   CORE_ADDR int_buffer;
   double freg_buffer;
 
@@ -1497,7 +1639,7 @@ hppa_push_dummy_frame (void)
 
   for (regnum = FP0_REGNUM; regnum < NUM_REGS; regnum++)
     {
-      deprecated_read_register_bytes (REGISTER_BYTE (regnum),
+      deprecated_read_register_bytes (DEPRECATED_REGISTER_BYTE (regnum),
                                      (char *) &freg_buffer, 8);
       sp = push_bytes (sp, (char *) &freg_buffer, 8);
     }
@@ -1554,15 +1696,15 @@ find_dummy_frame_regs (struct frame_info *frame,
 void
 hppa_pop_frame (void)
 {
-  register struct frame_info *frame = get_current_frame ();
-  register CORE_ADDR fp, npc, target_pc;
-  register int regnum;
+  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 = get_frame_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 */
@@ -1578,7 +1720,7 @@ hppa_pop_frame (void)
     if (fsr[regnum])
       {
        read_memory (fsr[regnum], (char *) &freg_buffer, 8);
-       deprecated_write_register_bytes (REGISTER_BYTE (regnum),
+       deprecated_write_register_bytes (DEPRECATED_REGISTER_BYTE (regnum),
                                         (char *) &freg_buffer, 8);
       }
 
@@ -1734,7 +1876,7 @@ hppa_push_arguments (int nargs, struct value **args, CORE_ADDR sp,
 
   /* The value of SP as it was passed into this function after
      aligning.  */
-  CORE_ADDR orig_sp = STACK_ALIGN (sp);
+  CORE_ADDR orig_sp = DEPRECATED_STACK_ALIGN (sp);
 
   /* The number of stack bytes occupied by the current argument.  */
   int bytes_reserved;
@@ -1797,7 +1939,7 @@ hppa_push_arguments (int nargs, struct value **args, CORE_ADDR sp,
 
      The ABIs also mandate minimum stack alignments which we must
      preserve.  */
-  cum_bytes_aligned = STACK_ALIGN (cum_bytes_reserved);
+  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.  */
@@ -1904,7 +2046,7 @@ hppa_push_arguments (int nargs, struct value **args, CORE_ADDR sp,
 
      The ABI also mandates minimum stack alignments which we must
      preserve.  */
-  cum_bytes_aligned = STACK_ALIGN (cum_bytes_reserved);
+  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.
@@ -1924,27 +2066,6 @@ hppa_push_arguments (int nargs, struct value **args, CORE_ADDR sp,
 
 #endif
 
-/* elz: this function returns a value which is built looking at the given address.
-   It is called from call_function_by_hand, in case we need to return a 
-   value which is larger than 64 bits, and it is stored in the stack rather than 
-   in the registers r28 and r29 or fr4.
-   This function does the same stuff as value_being_returned in values.c, but
-   gets the value from the stack rather than from the buffer where all the
-   registers were saved when the function called completed. */
-struct value *
-hppa_value_returned_from_stack (register struct type *valtype, CORE_ADDR addr)
-{
-  register struct value *val;
-
-  val = allocate_value (valtype);
-  CHECK_TYPEDEF (valtype);
-  target_read_memory (addr, VALUE_CONTENTS_RAW (val), TYPE_LENGTH (valtype));
-
-  return val;
-}
-
-
-
 /* 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
@@ -2237,7 +2358,7 @@ hppa_fix_call_dummy (char *dummy, CORE_ADDR pc, CORE_ADDR fun, int nargs,
          {
            stub_symbol
              = lookup_minimal_symbol_solib_trampoline
-             (DEPRECATED_SYMBOL_NAME (funsymbol), NULL, objfile);
+             (DEPRECATED_SYMBOL_NAME (funsymbol), objfile);
 
            if (!stub_symbol)
              stub_symbol = lookup_minimal_symbol (DEPRECATED_SYMBOL_NAME (funsymbol),
@@ -2494,7 +2615,7 @@ hppa_target_write_pc (CORE_ADDR v, ptid_t ptid)
     write_register_pid (31, v | 0x3, ptid);
 
   write_register_pid (PC_REGNUM, v, ptid);
-  write_register_pid (NPC_REGNUM, v + 4, ptid);
+  write_register_pid (PCOQ_TAIL_REGNUM, v + 4, ptid);
 }
 
 /* return the alignment of a type in bytes. Structures have the maximum
@@ -2537,13 +2658,14 @@ hppa_alignof (struct type *type)
 void
 pa_do_registers_info (int regnum, int fpregs)
 {
-  char raw_regs[REGISTER_BYTES];
+  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 + REGISTER_BYTE (i));
+    frame_register_read (deprecated_selected_frame, i,
+                        raw_regs + DEPRECATED_REGISTER_BYTE (i));
 
   if (regnum == -1)
     pa_print_registers (raw_regs, regnum, fpregs);
@@ -2581,13 +2703,14 @@ void
 pa_do_strcat_registers_info (int regnum, int fpregs, struct ui_file *stream,
                             enum precision_type precision)
 {
-  char raw_regs[REGISTER_BYTES];
+  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 + REGISTER_BYTE (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);
@@ -2634,7 +2757,7 @@ pa_register_look_aside (char *raw_regs, int regnum, long *raw_val)
 
   int regaddr;
   unsigned int offset;
-  register int i;
+  int i;
   int start;
 
 
@@ -2656,7 +2779,7 @@ pa_register_look_aside (char *raw_regs, int regnum, long *raw_val)
 
   if (!is_pa_2)
     {
-      raw_val[1] = *(long *) (raw_regs + REGISTER_BYTE (regnum));
+      raw_val[1] = *(long *) (raw_regs + DEPRECATED_REGISTER_BYTE (regnum));
       return;
     }
 
@@ -2842,13 +2965,13 @@ pa_print_fp_reg (int i)
   frame_register_read (deprecated_selected_frame, i, raw_buffer);
 
   /* Put it in the buffer.  No conversions are ever necessary.  */
-  memcpy (virtual_buffer, raw_buffer, REGISTER_RAW_SIZE (i));
+  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);
 
-  val_print (REGISTER_VIRTUAL_TYPE (i), virtual_buffer, 0, 0, gdb_stdout, 0,
+  val_print (DEPRECATED_REGISTER_VIRTUAL_TYPE (i), virtual_buffer, 0, 0, gdb_stdout, 0,
             1, 0, Val_pretty_default);
   printf_filtered ("\n");
 
@@ -2860,8 +2983,8 @@ pa_print_fp_reg (int i)
       frame_register_read (deprecated_selected_frame, i + 1, raw_buffer);
 
       /* Copy it into the appropriate part of the virtual buffer.  */
-      memcpy (virtual_buffer + REGISTER_RAW_SIZE (i), raw_buffer,
-             REGISTER_RAW_SIZE (i));
+      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);
@@ -2888,7 +3011,7 @@ pa_strcat_fp_reg (int i, struct ui_file *stream, enum precision_type precision)
   frame_register_read (deprecated_selected_frame, i, raw_buffer);
 
   /* Put it in the buffer.  No conversions are ever necessary.  */
-  memcpy (virtual_buffer, raw_buffer, REGISTER_RAW_SIZE (i));
+  memcpy (virtual_buffer, raw_buffer, DEPRECATED_REGISTER_RAW_SIZE (i));
 
   if (precision == double_precision && (i % 2) == 0)
     {
@@ -2899,7 +3022,8 @@ pa_strcat_fp_reg (int i, struct ui_file *stream, enum precision_type precision)
       frame_register_read (deprecated_selected_frame, i + 1, raw_buf);
 
       /* Copy it into the appropriate part of the virtual buffer.  */
-      memcpy (virtual_buffer + REGISTER_RAW_SIZE (i), raw_buf, REGISTER_RAW_SIZE (i));
+      memcpy (virtual_buffer + DEPRECATED_REGISTER_RAW_SIZE (i), raw_buf,
+             DEPRECATED_REGISTER_RAW_SIZE (i));
 
       val_print (builtin_type_double, virtual_buffer, 0, 0, stream, 0,
                 1, 0, Val_pretty_default);
@@ -2907,7 +3031,7 @@ pa_strcat_fp_reg (int i, struct ui_file *stream, enum precision_type precision)
     }
   else
     {
-      val_print (REGISTER_VIRTUAL_TYPE (i), virtual_buffer, 0, 0, stream, 0,
+      val_print (DEPRECATED_REGISTER_VIRTUAL_TYPE (i), virtual_buffer, 0, 0, stream, 0,
                 1, 0, Val_pretty_default);
     }
 
@@ -2953,8 +3077,9 @@ hppa_in_solib_call_trampoline (CORE_ADDR pc, char *name)
 
     sec = SYMBOL_BFD_SECTION (minsym);
 
-    if (sec->vma <= pc
-       && sec->vma + sec->_cooked_size < pc)
+    if (bfd_get_section_vma (sec->owner, sec) <= pc
+       && pc < (bfd_get_section_vma (sec->owner, sec)
+                + bfd_section_size (sec->owner, sec)))
       return 0;
 
     /* We might be in a stub.  Peek at the instructions.  Stubs are 3
@@ -3260,7 +3385,7 @@ hppa_skip_trampoline_code (CORE_ADDR pc)
          ALL_MSYMBOLS (objfile, msymbol)
          {
            if (MSYMBOL_TYPE (msymbol) == mst_text
-               && STREQ (DEPRECATED_SYMBOL_NAME (msymbol), DEPRECATED_SYMBOL_NAME (msym)))
+               && DEPRECATED_STREQ (DEPRECATED_SYMBOL_NAME (msymbol), DEPRECATED_SYMBOL_NAME (msym)))
              {
                function_found = 1;
                break;
@@ -4027,7 +4152,7 @@ hppa_frame_find_saved_regs (struct frame_info *frame_info,
              && extract_14 (inst) >= 0)
            frame_saved_regs[reg] = get_frame_base (frame_info);
          /* A std has explicit post_modify forms.  */
-         else if ((inst & 0xfc00000c0) == 0x70000008)
+         else if ((inst & 0xfc00000c) == 0x70000008)
            frame_saved_regs[reg] = get_frame_base (frame_info);
          else
            {
@@ -4107,12 +4232,303 @@ hppa_frame_find_saved_regs (struct frame_info *frame_info,
    that do not yet implement DEPRECATED_FRAME_INIT_SAVED_REGS.  */
 /* Find the addresses in which registers are saved in FRAME.  */
 
-void
+static void
 hppa_frame_init_saved_regs (struct frame_info *frame)
 {
-  if (get_frame_saved_regs (frame) == NULL)
+  if (deprecated_get_frame_saved_regs (frame) == NULL)
     frame_saved_regs_zalloc (frame);
-  hppa_frame_find_saved_regs (frame, get_frame_saved_regs (frame));
+  hppa_frame_find_saved_regs (frame, deprecated_get_frame_saved_regs (frame));
+}
+
+struct hppa_frame_cache
+{
+  CORE_ADDR base;
+  struct trad_frame_saved_reg *saved_regs;
+};
+
+static struct hppa_frame_cache *
+hppa_frame_cache (struct frame_info *next_frame, void **this_cache)
+{
+  struct hppa_frame_cache *cache;
+  long saved_gr_mask;
+  long saved_fr_mask;
+  CORE_ADDR this_sp;
+  long frame_size;
+  struct unwind_table_entry *u;
+  int i;
+
+  if ((*this_cache) != NULL)
+    return (*this_cache);
+  cache = FRAME_OBSTACK_ZALLOC (struct hppa_frame_cache);
+  (*this_cache) = cache;
+  cache->saved_regs = trad_frame_alloc_saved_regs (next_frame);
+
+  /* Yow! */
+  u = find_unwind_entry (frame_func_unwind (next_frame));
+  if (!u)
+    return;
+
+  /* Turn the Entry_GR field into a bitmask.  */
+  saved_gr_mask = 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;
+       
+      saved_gr_mask |= (1 << i);
+    }
+
+  /* Turn the Entry_FR field into a bitmask too.  */
+  saved_fr_mask = 0;
+  for (i = 12; i < u->Entry_FR + 12; i++)
+    saved_fr_mask |= (1 << i);
+
+  /* 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.  */
+  {
+    int final_iteration = 0;
+    CORE_ADDR pc;
+    CORE_ADDR end_pc = skip_prologue_using_sal (pc);
+    int looking_for_sp = u->Save_SP;
+    int looking_for_rp = u->Save_RP;
+    int fp_loc = -1;
+    if (end_pc == 0)
+      end_pc = frame_pc_unwind (next_frame);
+    frame_size = 0;
+    for (pc = frame_func_unwind (next_frame);
+        ((saved_gr_mask || saved_fr_mask
+          || looking_for_sp || looking_for_rp
+          || frame_size < (u->Total_frame_size << 3))
+         && pc <= end_pc);
+        pc += 4)
+      {
+       int reg;
+       char buf4[4];
+       long status = target_read_memory (pc, buf4, sizeof buf4);
+       long inst = extract_unsigned_integer (buf4, sizeof buf4);
+       
+       /* Note the interesting effects of this instruction.  */
+       frame_size += 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) */
+         {
+           looking_for_rp = 0;
+           cache->saved_regs[RP_REGNUM].addr = -20;
+         }
+       else if (inst == 0x0fc212c1) /* std rp,-0x10(sr0,sp) */
+         {
+           looking_for_rp = 0;
+           cache->saved_regs[RP_REGNUM].addr = -16;
+         }
+       
+       /* Check to see 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) */
+         {
+           looking_for_sp = 0;
+           cache->saved_regs[DEPRECATED_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))
+         {
+           saved_gr_mask &= ~(1 << reg);
+           if ((inst >> 26) == 0x1b && extract_14 (inst) >= 0)
+             /* stwm with a positive displacement is a _post_
+                _modify_.  */
+             cache->saved_regs[reg].addr = 0;
+           else if ((inst & 0xfc00000c) == 0x70000008)
+             /* A std has explicit post_modify forms.  */
+             cache->saved_regs[reg].addr = 0;
+           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);
+               
+               /* Handle code with and without frame pointers.  */
+               if (u->Save_SP)
+                 cache->saved_regs[reg].addr = offset;
+               else
+                 cache->saved_regs[reg].addr = (u->Total_frame_size << 3) + offset;
+             }
+         }
+
+       /* GCC handles callee saved FP regs a little differently.  
+          
+          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);
+       
+       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.  */
+           saved_fr_mask &= ~(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.  */
+               cache->saved_regs[reg + FP4_REGNUM + 4].addr = 0;
+               fp_loc = 8;
+             }
+           else
+             {
+               cache->saved_regs[reg + FP0_REGNUM + 4].addr = fp_loc;
+               fp_loc += 8;
+             }
+         }
+       
+       /* Quit if we hit any kind of branch the previous iteration. */
+       if (final_iteration)
+         break;
+       /* We want to look precisely one instruction beyond the branch
+          if we have not found everything yet.  */
+       if (is_branch (inst))
+         final_iteration = 1;
+      }
+  }
+
+  {
+    /* 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);
+    /* 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))
+      /* 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.  */
+      cache->base = read_memory_integer (this_sp, TARGET_PTR_BIT / 8);
+    else
+      /* 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);
+  }
+
+  /* The PC is found in the "return register".  */
+  if (u->Millicode)
+    cache->saved_regs[PC_REGNUM] = cache->saved_regs[31];
+  else
+    cache->saved_regs[PC_REGNUM] = cache->saved_regs[RP_REGNUM];
+
+  {
+    /* Convert all the offsets into addresses.  */
+    int reg;
+    for (reg = 0; reg < NUM_REGS; reg++)
+      {
+       if (trad_frame_addr_p (cache->saved_regs, reg))
+         cache->saved_regs[reg].addr += cache->base;
+      }
+  }
+
+  return (*this_cache);
+}
+
+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));
+}
+
+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)
+{
+  struct hppa_frame_cache *info = hppa_frame_cache (next_frame, this_cache);
+  trad_frame_prev_register (next_frame, info->saved_regs, regnum,
+                           optimizedp, lvalp, addrp, realnump, valuep);
+}
+
+static const struct frame_unwind hppa_frame_unwind =
+{
+  NORMAL_FRAME,
+  hppa_frame_this_id,
+  hppa_frame_prev_register
+};
+
+static const struct frame_unwind *
+hppa_frame_unwind_sniffer (struct frame_info *next_frame)
+{
+  return &hppa_frame_unwind;
+}
+
+static CORE_ADDR
+hppa_frame_base_address (struct frame_info *next_frame,
+                               void **this_cache)
+{
+  struct hppa_frame_cache *info = hppa_frame_cache (next_frame,
+                                                          this_cache);
+  return info->base;
+}
+
+static const struct frame_base hppa_frame_base = {
+  &hppa_frame_unwind,
+  hppa_frame_base_address,
+  hppa_frame_base_address,
+  hppa_frame_base_address
+};
+
+static const struct frame_base *
+hppa_frame_base_sniffer (struct frame_info *next_frame)
+{
+  return &hppa_frame_base;
+}
+
+static struct frame_id
+hppa_unwind_dummy_id (struct gdbarch *gdbarch, struct frame_info *next_frame)
+{
+  return frame_id_build (frame_unwind_register_unsigned (next_frame,
+                                                        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.
@@ -4642,92 +5058,6 @@ unwind_command (char *exp, int from_tty)
   pin (Total_frame_size);
 }
 
-#ifdef PREPARE_TO_PROCEED
-
-/* If the user has switched threads, and there is a breakpoint
-   at the old thread's pc location, then switch to that thread
-   and return TRUE, else return FALSE and don't do a thread
-   switch (or rather, don't seem to have done a thread switch).
-
-   Ptrace-based gdb will always return FALSE to the thread-switch
-   query, and thus also to PREPARE_TO_PROCEED.
-
-   The important thing is whether there is a BPT instruction,
-   not how many user breakpoints there are.  So we have to worry
-   about things like these:
-
-   o  Non-bp stop -- NO
-
-   o  User hits bp, no switch -- NO
-
-   o  User hits bp, switches threads -- YES
-
-   o  User hits bp, deletes bp, switches threads -- NO
-
-   o  User hits bp, deletes one of two or more bps
-   at that PC, user switches threads -- YES
-
-   o  Plus, since we're buffering events, the user may have hit a
-   breakpoint, deleted the breakpoint and then gotten another
-   hit on that same breakpoint on another thread which
-   actually hit before the delete. (FIXME in breakpoint.c
-   so that "dead" breakpoints are ignored?) -- NO
-
-   For these reasons, we have to violate information hiding and
-   call "breakpoint_here_p".  If core gdb thinks there is a bpt
-   here, that's what counts, as core gdb is the one which is
-   putting the BPT instruction in and taking it out.
-
-   Note that this implementation is potentially redundant now that
-   default_prepare_to_proceed() has been added.
-
-   FIXME This may not support switching threads after Ctrl-C
-   correctly. The default implementation does support this. */
-int
-hppa_prepare_to_proceed (void)
-{
-  pid_t old_thread;
-  pid_t current_thread;
-
-  old_thread = hppa_switched_threads (PIDGET (inferior_ptid));
-  if (old_thread != 0)
-    {
-      /* Switched over from "old_thread".  Try to do
-         as little work as possible, 'cause mostly
-         we're going to switch back. */
-      CORE_ADDR new_pc;
-      CORE_ADDR old_pc = read_pc ();
-
-      /* Yuk, shouldn't use global to specify current
-         thread.  But that's how gdb does it. */
-      current_thread = PIDGET (inferior_ptid);
-      inferior_ptid = pid_to_ptid (old_thread);
-
-      new_pc = read_pc ();
-      if (new_pc != old_pc     /* If at same pc, no need */
-         && breakpoint_here_p (new_pc))
-       {
-         /* User hasn't deleted the BP.
-            Return TRUE, finishing switch to "old_thread". */
-         flush_cached_frames ();
-         registers_changed ();
-#if 0
-         printf ("---> PREPARE_TO_PROCEED (was %d, now %d)!\n",
-                 current_thread, PIDGET (inferior_ptid));
-#endif
-
-         return 1;
-       }
-
-      /* Otherwise switch back to the user-chosen thread. */
-      inferior_ptid = pid_to_ptid (current_thread);
-      new_pc = read_pc ();     /* Re-prime register cache */
-    }
-
-  return 0;
-}
-#endif /* PREPARE_TO_PROCEED */
-
 void
 hppa_skip_permanent_breakpoint (void)
 {
@@ -4758,7 +5088,7 @@ hppa_skip_permanent_breakpoint (void)
    Called only in the context of the "return" command.  */
 
 void
-hppa_store_return_value (struct type *type, char *valbuf)
+hppa32_store_return_value (struct type *type, char *valbuf)
 {
   /* For software floating point, the return value goes into the
      integer registers.  But we do not have any flag to key this on,
@@ -4766,16 +5096,42 @@ hppa_store_return_value (struct type *type, char *valbuf)
 
      If its a float value, then we also store it into the floating
      point registers.  */
-  deprecated_write_register_bytes (REGISTER_BYTE (28)
+  deprecated_write_register_bytes (DEPRECATED_REGISTER_BYTE (28)
                                   + (TYPE_LENGTH (type) > 4
                                      ? (8 - TYPE_LENGTH (type))
                                      : (4 - TYPE_LENGTH (type))),
                                   valbuf, TYPE_LENGTH (type));
   if (TYPE_CODE (type) == TYPE_CODE_FLT)
-    deprecated_write_register_bytes (REGISTER_BYTE (FP4_REGNUM),
+    deprecated_write_register_bytes (DEPRECATED_REGISTER_BYTE (FP4_REGNUM),
                                     valbuf, TYPE_LENGTH (type));
 }
 
+/* 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);
+    }
+}
+
 /* Copy the function's return value into VALBUF.
 
    This function is called only in the context of "target function calls",
@@ -4784,22 +5140,50 @@ hppa_store_return_value (struct type *type, char *valbuf)
    "return" command.  */
 
 void
-hppa_extract_return_value (struct type *type, char *regbuf, char *valbuf)
+hppa32_extract_return_value (struct type *type, char *regbuf, char *valbuf)
 {
   if (TYPE_CODE (type) == TYPE_CODE_FLT)
-    memcpy (valbuf,
-           (char *)regbuf + REGISTER_BYTE (FP4_REGNUM),
-           TYPE_LENGTH (type));
+    memcpy (valbuf, regbuf + DEPRECATED_REGISTER_BYTE (FP4_REGNUM), TYPE_LENGTH (type));
   else
     memcpy (valbuf,
-           ((char *)regbuf
-            + REGISTER_BYTE (28)
+           (regbuf
+            + DEPRECATED_REGISTER_BYTE (28)
             + (TYPE_LENGTH (type) > 4
                ? (8 - TYPE_LENGTH (type))
                : (4 - TYPE_LENGTH (type)))),
            TYPE_LENGTH (type));
 }
 
+/* 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)
 {
@@ -4816,7 +5200,7 @@ hppa_inner_than (CORE_ADDR lhs, CORE_ADDR rhs)
 }
 
 CORE_ADDR
-hppa_stack_align (CORE_ADDR sp)
+hppa32_stack_align (CORE_ADDR sp)
 {
   /* elz: adjust the quantity to the next highest value which is
      64-bit aligned.  This is used in valops.c, when the sp is adjusted.
@@ -4824,6 +5208,13 @@ hppa_stack_align (CORE_ADDR sp)
   return ((sp % 8) ? (sp + 7) & -8 : sp);
 }
 
+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)
 {
@@ -4877,14 +5268,16 @@ hppa_register_raw_size (int reg_nr)
 int
 hppa_register_byte (int reg_nr)
 {
-  return reg_nr * 4;
+  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 *
-hppa_register_virtual_type (int reg_nr)
+hppa32_register_virtual_type (int reg_nr)
 {
    if (reg_nr < FP4_REGNUM)
      return builtin_type_int;
@@ -4892,6 +5285,18 @@ hppa_register_virtual_type (int reg_nr)
      return builtin_type_float;
 }
 
+/* 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)
+{
+   if (reg_nr < FP4_REGNUM)
+     return builtin_type_unsigned_long_long;
+   else
+     return builtin_type_double;
+}
+
 /* Store the address of the place in which to copy the structure the
    subroutine will return.  This is called from call_function.  */
 
@@ -4900,22 +5305,6 @@ hppa_store_struct_return (CORE_ADDR addr, CORE_ADDR sp)
 {
   write_register (28, addr);
 }
-
-CORE_ADDR
-hppa_extract_struct_value_address (char *regbuf)
-{
-  /* Extract from an array REGBUF containing the (raw) register state
-     the address in which a function should return its structure value,
-     as a CORE_ADDR (or an expression that can be used as one).  */
-  /* FIXME: brobecker 2002-12-26.
-     The current implementation is historical, but we should eventually
-     implement it in a more robust manner as it relies on the fact that
-     the address size is equal to the size of an int* _on the host_...
-     One possible implementation that crossed my mind is to use
-     extract_address.  */
-  return (*(int *)(regbuf + REGISTER_BYTE (28)));
-}
-
 /* Return True if REGNUM is not a register available to the user
    through ptrace().  */
 
@@ -4929,26 +5318,6 @@ hppa_cannot_store_register (int regnum)
 
 }
 
-CORE_ADDR
-hppa_frame_args_address (struct frame_info *fi)
-{
-  return get_frame_base (fi);
-}
-
-CORE_ADDR
-hppa_frame_locals_address (struct frame_info *fi)
-{
-  return get_frame_base (fi);
-}
-
-int
-hppa_frame_num_args (struct frame_info *frame)
-{
-  /* We can't tell how many args there are now that the C compiler delays
-     popping them.  */
-  return -1;
-}
-
 CORE_ADDR
 hppa_smash_text_address (CORE_ADDR addr)
 {
@@ -4962,9 +5331,55 @@ hppa_smash_text_address (CORE_ADDR addr)
   return (addr &= ~0x3);
 }
 
+/* Get the ith function argument for the current function.  */
+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);
+  return addr;
+}
+
+/* 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:
+
+     /usr/ccs/bin/cc    HP92453-01 A.11.01.21
+     /opt/ansic/bin/cc  HP92453-01 B.11.11.28706.GP
+     /opt/aCC/bin/aCC   B3910B A.03.45
+     gcc                gcc 3.3.2 native hppa2.0w-hp-hpux11.11
+
+     cc            : 1 2 4 4 8 : 4 8 -- : 4 4
+     ansic +DA1.1  : 1 2 4 4 8 : 4 8 16 : 4 4
+     ansic +DA2.0  : 1 2 4 4 8 : 4 8 16 : 4 4
+     ansic +DA2.0W : 1 2 4 8 8 : 4 8 16 : 8 8
+     acc   +DA1.1  : 1 2 4 4 8 : 4 8 16 : 4 4
+     acc   +DA2.0  : 1 2 4 4 8 : 4 8 16 : 4 4
+     acc   +DA2.0W : 1 2 4 8 8 : 4 8 16 : 8 8
+     gcc           : 1 2 4 4 8 : 4 8 16 : 4 4
+
+   Each line is:
+
+     compiler and options
+     char, short, int, long, long long
+     float, double, long double
+     char *, void (*)()
+
+   So all these compilers use either ILP32 or LP64 model.
+   TODO: gcc has more options so it needs more investigation.
+
+   For floating point types, see:
+
+     http://docs.hp.com/hpux/pdf/B3906-90006.pdf
+     HP-UX floating-point guide, hpux 11.00
+
+   -- chastain 2003-12-18  */
+
 static struct gdbarch *
 hppa_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 {
+  struct gdbarch_tdep *tdep;
   struct gdbarch *gdbarch;
   
   /* Try to determine the ABI of the object we are loading.  */
@@ -4981,65 +5396,159 @@ hppa_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
     return (arches->gdbarch);
 
   /* If none found, then allocate and initialize one.  */
-  gdbarch = gdbarch_alloc (&info, NULL);
+  tdep = XMALLOC (struct gdbarch_tdep);
+  gdbarch = gdbarch_alloc (&info, tdep);
+
+  /* Determine from the bfd_arch_info structure if we are dealing with
+     a 32 or 64 bits architecture.  If the bfd_arch_info is not available,
+     then default to a 32bit machine.  */
+  if (info.bfd_arch_info != NULL)
+    tdep->bytes_per_address =
+      info.bfd_arch_info->bits_per_address / info.bfd_arch_info->bits_per_byte;
+  else
+    tdep->bytes_per_address = 4;
 
-  /* Hook in ABI-specific overrides, if they have been registered.  */
-  gdbarch_init_osabi (info, gdbarch);
+  /* 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)
+    {
+      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);
+        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);
+        break;
+      default:
+        internal_error (__FILE__, __LINE__, "Unsupported address size: %d",
+                        tdep->bytes_per_address);
+    }
 
-  set_gdbarch_reg_struct_has_addr (gdbarch, hppa_reg_struct_has_addr);
-  set_gdbarch_function_start_offset (gdbarch, 0);
+  /* 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);
+
+  /* The following gdbarch vector elements are the same in both ILP32
+     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);
+
+  /* The following gdbarch vector elements do not depend on the address
+     size, or in any other gdbarch element previously set.  */
   set_gdbarch_skip_prologue (gdbarch, hppa_skip_prologue);
   set_gdbarch_skip_trampoline_code (gdbarch, hppa_skip_trampoline_code);
   set_gdbarch_in_solib_call_trampoline (gdbarch, hppa_in_solib_call_trampoline);
   set_gdbarch_in_solib_return_trampoline (gdbarch,
                                           hppa_in_solib_return_trampoline);
-  set_gdbarch_deprecated_saved_pc_after_call (gdbarch, hppa_saved_pc_after_call);
   set_gdbarch_inner_than (gdbarch, hppa_inner_than);
-  set_gdbarch_stack_align (gdbarch, hppa_stack_align);
-  set_gdbarch_decr_pc_after_break (gdbarch, 0);
-  set_gdbarch_deprecated_register_size (gdbarch, 4);
-  set_gdbarch_num_regs (gdbarch, hppa_num_regs);
+  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_npc_regnum (gdbarch, PCOQ_TAIL_REGNUM);
-  set_gdbarch_register_raw_size (gdbarch, hppa_register_raw_size);
-  set_gdbarch_register_bytes (gdbarch, hppa_num_regs * 4);
-  set_gdbarch_register_byte (gdbarch, hppa_register_byte);
-  set_gdbarch_register_virtual_size (gdbarch, hppa_register_raw_size);
-  set_gdbarch_deprecated_max_register_raw_size (gdbarch, 4);
+  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_register_virtual_type (gdbarch, hppa_register_virtual_type);
-  set_gdbarch_deprecated_store_struct_return (gdbarch, hppa_store_struct_return);
-  set_gdbarch_deprecated_extract_return_value (gdbarch,
-                                               hppa_extract_return_value);
-  set_gdbarch_use_struct_convention (gdbarch, hppa_use_struct_convention);
-  set_gdbarch_deprecated_store_return_value (gdbarch, hppa_store_return_value);
-  set_gdbarch_deprecated_extract_struct_value_address
-    (gdbarch, hppa_extract_struct_value_address);
   set_gdbarch_cannot_store_register (gdbarch, hppa_cannot_store_register);
-  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_frameless_function_invocation
-    (gdbarch, hppa_frameless_function_invocation);
-  set_gdbarch_deprecated_frame_saved_pc (gdbarch, hppa_frame_saved_pc);
-  set_gdbarch_frame_args_address (gdbarch, hppa_frame_args_address);
-  set_gdbarch_frame_locals_address (gdbarch, hppa_frame_locals_address);
-  set_gdbarch_frame_num_args (gdbarch, hppa_frame_num_args);
-  set_gdbarch_frame_args_skip (gdbarch, 0);
-  set_gdbarch_deprecated_push_dummy_frame (gdbarch, hppa_push_dummy_frame);
-  set_gdbarch_deprecated_pop_frame (gdbarch, hppa_pop_frame);
-  set_gdbarch_deprecated_call_dummy_length (gdbarch, INSTRUCTION_SIZE * 28);
-  /* set_gdbarch_deprecated_fix_call_dummy (gdbarch, hppa_fix_call_dummy); */
-  set_gdbarch_deprecated_push_arguments (gdbarch, hppa_push_arguments);
+  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);
+
+  set_gdbarch_print_insn (gdbarch, print_insn_hppa);
+
+  /* When a hardware watchpoint triggers, we'll move the inferior past
+     it by removing all eventpoints; stepping past the instruction
+     that caused the trigger; reinserting eventpoints; and checking
+     whether any watched location changed.  */
+  set_gdbarch_have_nonsteppable_watchpoint (gdbarch, 1);
+
+  /* Inferior function call methods.  */
+  if (0)
+    {
+    }
+  else
+    {
+      switch (tdep->bytes_per_address)
+       {
+       case 4:
+         set_gdbarch_deprecated_call_dummy_length (gdbarch, hppa32_call_dummy_length);
+         set_gdbarch_deprecated_stack_align (gdbarch, hppa32_stack_align);
+         set_gdbarch_deprecated_reg_struct_has_addr (gdbarch, hppa_reg_struct_has_addr);
+         break;
+       case 8:
+         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);
+    }
+      
+  /* Struct return methods.  */
+  if (0)
+    {
+    }
+  else
+    {
+      switch (tdep->bytes_per_address)
+       {
+       case 4:
+         set_gdbarch_deprecated_extract_return_value (gdbarch, hppa32_extract_return_value);
+         set_gdbarch_use_struct_convention (gdbarch, hppa32_use_struct_convention);
+         set_gdbarch_deprecated_store_return_value (gdbarch, hppa32_store_return_value);
+         break;
+       case 8:
+         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);
+         break;
+       }
+      set_gdbarch_deprecated_store_struct_return (gdbarch, hppa_store_struct_return);
+    }
+      
+  /* Frame unwind methods.  */
+  if (0)
+    {
+      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);
+    }
+  else
+    {
+      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);
+    }
+
+  /* Hook in ABI-specific overrides, if they have been registered.  */
+  gdbarch_init_osabi (info, gdbarch);
+
   return gdbarch;
 }
 
@@ -5058,7 +5567,6 @@ _initialize_hppa_tdep (void)
   void break_at_finish_at_depth_command (char *arg, int from_tty);
 
   gdbarch_register (bfd_arch_hppa, hppa_gdbarch_init, hppa_dump_tdep);
-  deprecated_tm_print_insn = print_insn_hppa;
 
   add_cmd ("unwind", class_maintenance, unwind_command,
           "Print unwind table entry at given address.",
This page took 0.042814 seconds and 4 git commands to generate.