/* 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);
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);
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
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;
}
{
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;
}
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
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.
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;
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
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
/* 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);
/* 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);
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)
{
}
-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)
{
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)
{
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);
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_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;
}