* hppa-tdep.c: Include "dis-asm.h". Fixes a build failure.
[deliverable/binutils-gdb.git] / gdb / hppa-tdep.c
index db8d510554202160aaf5c437b2e6a39ce380c292..6148915557e3bd7a3f3ca66e7e0d9626c9869cf9 100644 (file)
@@ -37,6 +37,7 @@
 /* For argument passing to the inferior */
 #include "symtab.h"
 #include "infcall.h"
+#include "dis-asm.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);
@@ -107,9 +141,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,16 +176,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);
+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);
 CORE_ADDR hppa_extract_struct_value_address (char *regbuf);
 int hppa_cannot_store_register (int regnum);
 void hppa_init_extra_frame_info (int fromleaf, struct frame_info *frame);
@@ -163,7 +201,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 +235,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 +269,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 +329,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 +350,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 +368,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
@@ -642,6 +696,96 @@ find_unwind_entry (CORE_ADDR pc)
   return NULL;
 }
 
+const unsigned char *
+hppa_breakpoint_from_pc (CORE_ADDR *pc, int *len)
+{
+  static const 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.
 
@@ -1973,10 +2117,10 @@ find_stub_with_shl_get (struct minimal_symbol *function, CORE_ADDR handle)
 
   args = alloca (sizeof (struct value *) * 8);         /* 6 for the arguments and one null one??? */
   funcval = find_function_in_inferior ("__d_shl_get");
-  get_sym = lookup_symbol ("__d_shl_get", NULL, VAR_NAMESPACE, NULL, NULL);
+  get_sym = lookup_symbol ("__d_shl_get", NULL, VAR_DOMAIN, NULL, NULL);
   buff_minsym = lookup_minimal_symbol ("__buffer", NULL, NULL);
   msymbol = lookup_minimal_symbol ("__shldp", NULL, NULL);
-  symbol2 = lookup_symbol ("__shldp", NULL, VAR_NAMESPACE, NULL, NULL);
+  symbol2 = lookup_symbol ("__shldp", NULL, VAR_DOMAIN, NULL, NULL);
   endo_buff_addr = SYMBOL_VALUE_ADDRESS (buff_minsym);
   namelen = strlen (DEPRECATED_SYMBOL_NAME (function));
   value_return_addr = endo_buff_addr + namelen;
@@ -2529,7 +2673,7 @@ 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
@@ -2573,7 +2717,7 @@ 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
@@ -2630,7 +2774,7 @@ pa_register_look_aside (char *raw_regs, int regnum, long *raw_val)
   int start;
 
 
-  char *buf = alloca (max_register_size (current_gdbarch));
+  char buf[MAX_REGISTER_SIZE];
   long long reg_val;
 
   if (!know_which)
@@ -2827,8 +2971,8 @@ pa_strcat_registers (char *raw_regs, int regnum, int fpregs,
 static void
 pa_print_fp_reg (int i)
 {
-  char *raw_buffer = alloca (max_register_size (current_gdbarch));
-  char *virtual_buffer = alloca (max_register_size (current_gdbarch));
+  char raw_buffer[MAX_REGISTER_SIZE];
+  char virtual_buffer[MAX_REGISTER_SIZE];
 
   /* Get 32bits of data.  */
   frame_register_read (deprecated_selected_frame, i, raw_buffer);
@@ -2870,8 +3014,8 @@ pa_print_fp_reg (int i)
 static void
 pa_strcat_fp_reg (int i, struct ui_file *stream, enum precision_type precision)
 {
-  char *raw_buffer = alloca (max_register_size (current_gdbarch));
-  char *virtual_buffer = alloca (max_register_size (current_gdbarch));
+  char raw_buffer[MAX_REGISTER_SIZE];
+  char virtual_buffer[MAX_REGISTER_SIZE];
 
   fputs_filtered (REGISTER_NAME (i), stream);
   print_spaces_filtered (8 - strlen (REGISTER_NAME (i)), stream);
@@ -2885,7 +3029,7 @@ pa_strcat_fp_reg (int i, struct ui_file *stream, enum precision_type precision)
   if (precision == double_precision && (i % 2) == 0)
     {
 
-      char *raw_buf = alloca (max_register_size (current_gdbarch));
+      char raw_buf[MAX_REGISTER_SIZE];
 
       /* Get the data in raw format for the 2nd half.  */
       frame_register_read (deprecated_selected_frame, i + 1, raw_buf);
@@ -4345,7 +4489,7 @@ initialize_hp_cxx_exception_support (void)
 
   /* Next look for the catch enable flag provided in end.o */
   sym = lookup_symbol (HP_ACC_EH_catch_catch, (struct block *) NULL,
-                      VAR_NAMESPACE, 0, (struct symtab **) NULL);
+                      VAR_DOMAIN, 0, (struct symtab **) NULL);
   if (sym)                     /* sometimes present in debug info */
     {
       eh_catch_catch_addr = SYMBOL_VALUE_ADDRESS (sym);
@@ -4371,7 +4515,7 @@ initialize_hp_cxx_exception_support (void)
 
   /* Next look for the catch enable flag provided end.o */
   sym = lookup_symbol (HP_ACC_EH_catch_catch, (struct block *) NULL,
-                      VAR_NAMESPACE, 0, (struct symtab **) NULL);
+                      VAR_DOMAIN, 0, (struct symtab **) NULL);
   if (sym)                     /* sometimes present in debug info */
     {
       eh_catch_throw_addr = SYMBOL_VALUE_ADDRESS (sym);
@@ -4634,92 +4778,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)
 {
@@ -4750,7 +4808,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,
@@ -4768,6 +4826,32 @@ hppa_store_return_value (struct type *type, char *valbuf)
                                     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
+      (REGISTER_BYTE (FP4_REGNUM)
+        + DEPRECATED_REGISTER_SIZE - TYPE_LENGTH (type),
+       valbuf, TYPE_LENGTH (type));
+  else if (is_integral_type(type))
+    deprecated_write_register_bytes
+      (REGISTER_BYTE (28)
+        + DEPRECATED_REGISTER_SIZE - TYPE_LENGTH (type),
+       valbuf, TYPE_LENGTH (type));
+  else if (TYPE_LENGTH (type) <= 8)
+    deprecated_write_register_bytes
+      (REGISTER_BYTE (28),valbuf, TYPE_LENGTH (type));
+  else if (TYPE_LENGTH (type) <= 16)
+    {
+      deprecated_write_register_bytes (REGISTER_BYTE (28),valbuf, 8);
+      deprecated_write_register_bytes
+        (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",
@@ -4776,15 +4860,13 @@ 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 + REGISTER_BYTE (FP4_REGNUM), TYPE_LENGTH (type));
   else
     memcpy (valbuf,
-           ((char *)regbuf
+           (regbuf
             + REGISTER_BYTE (28)
             + (TYPE_LENGTH (type) > 4
                ? (8 - TYPE_LENGTH (type))
@@ -4792,6 +4874,34 @@ hppa_extract_return_value (struct type *type, char *regbuf, char *valbuf)
            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 + REGISTER_BYTE (FP4_REGNUM)
+             + DEPRECATED_REGISTER_SIZE - TYPE_LENGTH (type),
+            TYPE_LENGTH (type));
+  else if (is_integral_type(type))
+    memcpy (valbuf,
+            regbuf + REGISTER_BYTE (28)
+             + DEPRECATED_REGISTER_SIZE - TYPE_LENGTH (type),
+            TYPE_LENGTH (type));
+  else if (TYPE_LENGTH (type) <= 8)
+    memcpy (valbuf, regbuf + REGISTER_BYTE (28), TYPE_LENGTH (type));
+  else if (TYPE_LENGTH (type) <= 16)
+    {
+      memcpy (valbuf, regbuf + REGISTER_BYTE (28), 8);
+      memcpy (valbuf + 8, regbuf + REGISTER_BYTE (29), TYPE_LENGTH (type) - 8);
+    }
+}
+
 int
 hppa_reg_struct_has_addr (int gcc_p, struct type *type)
 {
@@ -4808,7 +4918,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.
@@ -4816,6 +4926,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)
 {
@@ -4869,14 +4986,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;
@@ -4884,6 +5003,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.  */
 
@@ -4921,26 +5052,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)
 {
@@ -4954,9 +5065,20 @@ 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;
+  frame_read_register (frame, R0_REGNUM + 26 - argi, &addr);
+  return addr;
+}
+
 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.  */
@@ -4973,12 +5095,70 @@ 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);
+        set_gdbarch_deprecated_call_dummy_length
+          (gdbarch, hppa32_call_dummy_length);
+        set_gdbarch_stack_align (gdbarch, hppa32_stack_align);
+        set_gdbarch_reg_struct_has_addr (gdbarch, hppa_reg_struct_has_addr);
+        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_num_regs (gdbarch, hppa64_num_regs);
+        set_gdbarch_register_name (gdbarch, hppa64_register_name);
+        set_gdbarch_deprecated_register_virtual_type
+          (gdbarch, hppa64_register_virtual_type);
+        set_gdbarch_deprecated_call_dummy_breakpoint_offset
+          (gdbarch, hppa64_call_dummy_breakpoint_offset);
+        set_gdbarch_deprecated_call_dummy_length
+          (gdbarch, hppa64_call_dummy_length);
+        set_gdbarch_stack_align (gdbarch, hppa64_stack_align);
+        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;
+      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);
+  /* 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_long_long_bit (gdbarch, 64);
+  set_gdbarch_ptr_bit (gdbarch, tdep->bytes_per_address * TARGET_CHAR_BIT);
+
+  /* The following gdbarch vector elements do not depend on the address
+     size, or in any other gdbarch element previously set.  */
   set_gdbarch_function_start_offset (gdbarch, 0);
   set_gdbarch_skip_prologue (gdbarch, hppa_skip_prologue);
   set_gdbarch_skip_trampoline_code (gdbarch, hppa_skip_trampoline_code);
@@ -4987,27 +5167,19 @@ hppa_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
                                           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);
@@ -5017,21 +5189,32 @@ hppa_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   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);
+
+  /* Hook in ABI-specific overrides, if they have been registered.  */
+  gdbarch_init_osabi (info, gdbarch);
+
   return gdbarch;
 }
 
@@ -5050,7 +5233,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.034034 seconds and 4 git commands to generate.