2003-07-28 Andrew Cagney <cagney@redhat.com>
[deliverable/binutils-gdb.git] / gdb / hppa-tdep.c
index d524bae33c13cd822bb4aa12b08e7972576dc24d..fed6cb181f896e7eca055e154b108910e214ad52 100644 (file)
 /* Some local constants.  */
 static const int hppa_num_regs = 128;
 
+/* 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 +129,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);
@@ -224,6 +243,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 +303,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 +324,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 +342,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 +670,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 *
+hppa_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 +2091,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 +2647,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 +2691,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
@@ -4345,7 +4463,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 +4489,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 +4752,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)
 {
@@ -4921,26 +4953,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,6 +4966,16 @@ 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)
 {
@@ -4996,13 +5018,14 @@ hppa_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   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_register_raw_size (gdbarch, hppa_register_raw_size);
+  set_gdbarch_deprecated_register_bytes (gdbarch, hppa_num_regs * 4);
+  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, 4);
   set_gdbarch_deprecated_max_register_virtual_size (gdbarch, 8);
-  set_gdbarch_register_virtual_type (gdbarch, hppa_register_virtual_type);
+  set_gdbarch_deprecated_register_virtual_type (gdbarch, hppa_register_virtual_type);
+  set_gdbarch_register_name (gdbarch, hppa_register_name);
   set_gdbarch_deprecated_store_struct_return (gdbarch, hppa_store_struct_return);
   set_gdbarch_deprecated_extract_return_value (gdbarch,
                                                hppa_extract_return_value);
@@ -5017,9 +5040,6 @@ 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);
@@ -5032,6 +5052,9 @@ hppa_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   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);
+
   return gdbarch;
 }
 
This page took 0.029191 seconds and 4 git commands to generate.