/* Target-dependent code for the HP PA-RISC architecture.
- Copyright (C) 1986, 1987, 1989, 1990, 1991, 1992, 1993, 1994, 1995,
- 1996, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+ Copyright (C) 1986, 1987, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996,
+ 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007
Free Software Foundation, Inc.
Contributed by the Center for Software Science at the
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
+ the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA. */
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "defs.h"
#include "bfd.h"
#include "completer.h"
#include "osabi.h"
#include "gdb_assert.h"
+#include "gdb_stdint.h"
#include "arch-utils.h"
/* For argument passing to the inferior */
#include "symtab.h"
#include "gdbcore.h"
#include "gdbcmd.h"
+#include "gdbtypes.h"
#include "objfiles.h"
#include "hppa-tdep.h"
table[i].Millicode = (tmp >> 30) & 0x1;
table[i].Millicode_save_sr0 = (tmp >> 29) & 0x1;
table[i].Region_description = (tmp >> 27) & 0x3;
- table[i].reserved1 = (tmp >> 26) & 0x1;
+ table[i].reserved = (tmp >> 26) & 0x1;
table[i].Entry_SR = (tmp >> 25) & 0x1;
table[i].Entry_FR = (tmp >> 21) & 0xf;
table[i].Entry_GR = (tmp >> 16) & 0x1f;
table[i].Frame_Extension_Millicode = (tmp >> 12) & 0x1;
table[i].Stack_Overflow_Check = (tmp >> 11) & 0x1;
table[i].Two_Instruction_SP_Increment = (tmp >> 10) & 0x1;
- table[i].Ada_Region = (tmp >> 9) & 0x1;
+ table[i].sr4export = (tmp >> 9) & 0x1;
table[i].cxx_info = (tmp >> 8) & 0x1;
table[i].cxx_try_catch = (tmp >> 7) & 0x1;
table[i].sched_entry_seq = (tmp >> 6) & 0x1;
- table[i].reserved2 = (tmp >> 5) & 0x1;
+ table[i].reserved1 = (tmp >> 5) & 0x1;
table[i].Save_SP = (tmp >> 4) & 0x1;
table[i].Save_RP = (tmp >> 3) & 0x1;
table[i].Save_MRP_in_frame = (tmp >> 2) & 0x1;
- table[i].extn_ptr_defined = (tmp >> 1) & 0x1;
+ table[i].save_r19 = (tmp >> 1) & 0x1;
table[i].Cleanup_defined = tmp & 0x1;
tmp = bfd_get_32 (objfile->obfd, (bfd_byte *) buf);
buf += 4;
table[i].MPE_XL_interrupt_marker = (tmp >> 31) & 0x1;
table[i].HP_UX_interrupt_marker = (tmp >> 30) & 0x1;
table[i].Large_frame = (tmp >> 29) & 0x1;
- table[i].Pseudo_SP_Set = (tmp >> 28) & 0x1;
- table[i].reserved4 = (tmp >> 27) & 0x1;
+ table[i].alloca_frame = (tmp >> 28) & 0x1;
+ table[i].reserved2 = (tmp >> 27) & 0x1;
table[i].Total_frame_size = tmp & 0x7ffffff;
/* Stub unwinds are handled elsewhere. */
{
if (hppa_debug)
fprintf_unfiltered (gdb_stdlog, "0x%s (cached) }\n",
- paddr_nz ((CORE_ADDR) ui->cache));
+ paddr_nz ((uintptr_t) ui->cache));
return ui->cache;
}
ui->cache = &ui->table[middle];
if (hppa_debug)
fprintf_unfiltered (gdb_stdlog, "0x%s }\n",
- paddr_nz ((CORE_ADDR) ui->cache));
+ paddr_nz ((uintptr_t) ui->cache));
return &ui->table[middle];
}
char buf[4];
int off;
- status = deprecated_read_memory_nobpt (pc, buf, 4);
+ status = read_memory_nobpt (pc, buf, 4);
if (status != 0)
return 0;
/* If a structure has to be returned, set up register 28 to hold its
address */
if (struct_return)
- write_register (28, struct_addr);
+ regcache_cooked_write_unsigned (regcache, 28, struct_addr);
gp = tdep->find_global_pointer (function);
if (gp != 0)
- write_register (19, gp);
+ regcache_cooked_write_unsigned (regcache, 19, gp);
/* Set the return address. */
if (!gdbarch_push_dummy_code_p (gdbarch))
}
CORE_ADDR
-hppa_read_pc (ptid_t ptid)
+hppa_read_pc (struct regcache *regcache)
{
ULONGEST ipsw;
- CORE_ADDR pc;
+ ULONGEST pc;
- ipsw = read_register_pid (HPPA_IPSW_REGNUM, ptid);
- pc = read_register_pid (HPPA_PCOQ_HEAD_REGNUM, ptid);
+ regcache_cooked_read_unsigned (regcache, HPPA_IPSW_REGNUM, &ipsw);
+ regcache_cooked_read_unsigned (regcache, HPPA_PCOQ_HEAD_REGNUM, &pc);
/* If the current instruction is nullified, then we are effectively
still executing the previous instruction. Pretend we are still
}
void
-hppa_write_pc (CORE_ADDR pc, ptid_t ptid)
+hppa_write_pc (struct regcache *regcache, CORE_ADDR pc)
{
- write_register_pid (HPPA_PCOQ_HEAD_REGNUM, pc, ptid);
- write_register_pid (HPPA_PCOQ_TAIL_REGNUM, pc + 4, ptid);
+ regcache_cooked_write_unsigned (regcache, HPPA_PCOQ_HEAD_REGNUM, pc);
+ regcache_cooked_write_unsigned (regcache, HPPA_PCOQ_TAIL_REGNUM, pc + 4);
}
/* return the alignment of a type in bytes. Structures have the maximum
old_save_sp = save_sp;
old_stack_remaining = stack_remaining;
- status = deprecated_read_memory_nobpt (pc, buf, 4);
+ status = read_memory_nobpt (pc, buf, 4);
inst = extract_unsigned_integer (buf, 4);
/* Yow! */
FIXME. Can still die if we have a mix of GR and FR argument
stores! */
- if (reg_num >= (TARGET_PTR_BIT == 64 ? 19 : 23) && reg_num <= 26)
+ if (reg_num >= (gdbarch_ptr_bit (current_gdbarch) == 64 ? 19 : 23)
+ && reg_num <= 26)
{
- while (reg_num >= (TARGET_PTR_BIT == 64 ? 19 : 23) && reg_num <= 26)
+ while (reg_num >= (gdbarch_ptr_bit (current_gdbarch) == 64 ? 19 : 23)
+ && reg_num <= 26)
{
pc += 4;
- status = deprecated_read_memory_nobpt (pc, buf, 4);
+ status = read_memory_nobpt (pc, buf, 4);
inst = extract_unsigned_integer (buf, 4);
if (status != 0)
return pc;
reg_num = inst_saves_fr (inst);
save_fr &= ~(1 << reg_num);
- status = deprecated_read_memory_nobpt (pc + 4, buf, 4);
+ status = read_memory_nobpt (pc + 4, buf, 4);
next_inst = extract_unsigned_integer (buf, 4);
/* Yow! */
save. */
if ((inst & 0xfc000000) == 0x34000000
&& inst_saves_fr (next_inst) >= 4
- && inst_saves_fr (next_inst) <= (TARGET_PTR_BIT == 64 ? 11 : 7))
+ && inst_saves_fr (next_inst)
+ <= (gdbarch_ptr_bit (current_gdbarch) == 64 ? 11 : 7))
{
/* So we drop into the code below in a reasonable state. */
reg_num = inst_saves_fr (next_inst);
This is a kludge as on the HP compiler sets this bit and it
never does prologue scheduling. So once we see one, skip past
all of them. */
- if (reg_num >= 4 && reg_num <= (TARGET_PTR_BIT == 64 ? 11 : 7))
+ if (reg_num >= 4
+ && reg_num <= (gdbarch_ptr_bit (current_gdbarch) == 64 ? 11 : 7))
{
- while (reg_num >= 4 && reg_num <= (TARGET_PTR_BIT == 64 ? 11 : 7))
+ while (reg_num >= 4
+ && reg_num
+ <= (gdbarch_ptr_bit (current_gdbarch) == 64 ? 11 : 7))
{
pc += 8;
- status = deprecated_read_memory_nobpt (pc, buf, 4);
+ status = read_memory_nobpt (pc, buf, 4);
inst = extract_unsigned_integer (buf, 4);
if (status != 0)
return pc;
if ((inst & 0xfc000000) != 0x34000000)
break;
- status = deprecated_read_memory_nobpt (pc + 4, buf, 4);
+ status = read_memory_nobpt (pc + 4, buf, 4);
next_inst = extract_unsigned_integer (buf, 4);
if (status != 0)
return pc;
return (skip_prologue_hard_way (pc, 1));
}
+/* Return an unwind entry that falls within the frame's code block. */
+static struct unwind_table_entry *
+hppa_find_unwind_entry_in_block (struct frame_info *f)
+{
+ CORE_ADDR pc = frame_unwind_address_in_block (f, NORMAL_FRAME);
+
+ /* FIXME drow/20070101: Calling gdbarch_addr_bits_remove on the
+ result of frame_unwind_address_in_block implies a problem.
+ The bits should have been removed earlier, before the return
+ value of frame_pc_unwind. That might be happening already;
+ if it isn't, it should be fixed. Then this call can be
+ removed. */
+ pc = gdbarch_addr_bits_remove (get_frame_arch (f), pc);
+ return find_unwind_entry (pc);
+}
+
struct hppa_frame_cache
{
CORE_ADDR base;
cache->saved_regs = trad_frame_alloc_saved_regs (next_frame);
/* Yow! */
- u = find_unwind_entry (frame_pc_unwind (next_frame));
+ u = hppa_find_unwind_entry_in_block (next_frame);
if (!u)
{
if (hppa_debug)
GCC code. */
{
int final_iteration = 0;
- CORE_ADDR pc, end_pc;
+ CORE_ADDR pc, start_pc, end_pc;
int looking_for_sp = u->Save_SP;
int looking_for_rp = u->Save_RP;
int fp_loc = -1;
/* We used to use frame_func_unwind () to locate the beginning of the
function to pass to skip_prologue (). However, when objects are
compiled without debug symbols, frame_func_unwind can return the wrong
- function (or 0). We can do better than that by using unwind records. */
+ function (or 0). We can do better than that by using unwind records.
+ This only works if the Region_description of the unwind record
+ indicates that it includes the entry point of the function.
+ HP compilers sometimes generate unwind records for regions that
+ do not include the entry or exit point of a function. GNU tools
+ do not do this. */
+
+ if ((u->Region_description & 0x2) == 0)
+ start_pc = u->region_start;
+ else
+ start_pc = frame_func_unwind (next_frame, NORMAL_FRAME);
- prologue_end = skip_prologue_hard_way (u->region_start, 0);
+ prologue_end = skip_prologue_hard_way (start_pc, 0);
end_pc = frame_pc_unwind (next_frame);
if (prologue_end != 0 && end_pc > prologue_end)
frame_size = 0;
- for (pc = u->region_start;
+ for (pc = start_pc;
((saved_gr_mask || saved_fr_mask
|| looking_for_sp || looking_for_rp
|| frame_size < (u->Total_frame_size << 3))
instead of Save_SP. */
fp = frame_unwind_register_unsigned (next_frame, HPPA_FP_REGNUM);
+
+ if (u->alloca_frame)
+ fp -= u->Total_frame_size << 3;
if (frame_pc_unwind (next_frame) >= prologue_end
- && u->Save_SP && fp != 0)
+ && (u->Save_SP || u->alloca_frame) && fp != 0)
{
cache->base = fp;
/* 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);
+ cache->base = read_memory_integer
+ (this_sp, gdbarch_ptr_bit (current_gdbarch) / 8);
if (hppa_debug)
fprintf_unfiltered (gdb_stdlog, " (base=0x%s) [saved]",
{
/* Convert all the offsets into addresses. */
int reg;
- for (reg = 0; reg < NUM_REGS; reg++)
+ for (reg = 0; reg < gdbarch_num_regs (current_gdbarch); reg++)
{
if (trad_frame_addr_p (cache->saved_regs, reg))
cache->saved_regs[reg].addr += cache->base;
struct unwind_table_entry *u;
info = hppa_frame_cache (next_frame, this_cache);
- u = find_unwind_entry (pc);
+ u = hppa_find_unwind_entry_in_block (next_frame);
(*this_id) = frame_id_build (info->base, u->region_start);
}
static const struct frame_unwind *
hppa_frame_unwind_sniffer (struct frame_info *next_frame)
{
- CORE_ADDR pc = frame_pc_unwind (next_frame);
-
- if (find_unwind_entry (pc))
+ if (hppa_find_unwind_entry_in_block (next_frame))
return &hppa_frame_unwind;
return NULL;
(*this_cache) = cache;
cache->saved_regs = trad_frame_alloc_saved_regs (next_frame);
- start_pc = frame_func_unwind (next_frame);
+ start_pc = frame_func_unwind (next_frame, NORMAL_FRAME);
if (start_pc)
{
CORE_ADDR cur_pc = frame_pc_unwind (next_frame);
{
struct hppa_frame_cache *info =
hppa_fallback_frame_cache (next_frame, this_cache);
- (*this_id) = frame_id_build (info->base, frame_func_unwind (next_frame));
+ (*this_id) = frame_id_build (info->base,
+ frame_func_unwind (next_frame, NORMAL_FRAME));
}
static void
= hppa_stub_frame_unwind_cache (next_frame, this_prologue_cache);
if (info)
- *this_id = frame_id_build (info->base, frame_func_unwind (next_frame));
+ *this_id = frame_id_build (info->base,
+ frame_func_unwind (next_frame, NORMAL_FRAME));
else
*this_id = null_frame_id;
}
static const struct frame_unwind *
hppa_stub_unwind_sniffer (struct frame_info *next_frame)
{
- CORE_ADDR pc = frame_pc_unwind (next_frame);
+ CORE_ADDR pc = frame_unwind_address_in_block (next_frame, NORMAL_FRAME);
struct gdbarch *gdbarch = get_frame_arch (next_frame);
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
if (pc == 0
|| (tdep->in_solib_call_trampoline != NULL
&& tdep->in_solib_call_trampoline (pc, NULL))
- || IN_SOLIB_RETURN_TRAMPOLINE (pc, NULL))
+ || gdbarch_in_solib_return_trampoline (current_gdbarch, pc, NULL))
return &hppa_stub_frame_unwind;
return NULL;
}
pif (Frame_Extension_Millicode);
pif (Stack_Overflow_Check);
pif (Two_Instruction_SP_Increment);
- pif (Ada_Region);
+ pif (sr4export);
+ pif (cxx_info);
+ pif (cxx_try_catch);
+ pif (sched_entry_seq);
pif (Save_SP);
pif (Save_RP);
pif (Save_MRP_in_frame);
- pif (extn_ptr_defined);
+ pif (save_r19);
pif (Cleanup_defined);
pif (MPE_XL_interrupt_marker);
pif (HP_UX_interrupt_marker);
pif (Large_frame);
+ pif (alloca_frame);
putchar_unfiltered ('\n');
if (regnum < HPPA_FP4_REGNUM)
return builtin_type_uint32;
else
- return builtin_type_ieee_single_big;
+ return builtin_type_ieee_single;
}
static struct type *
if (regnum < HPPA64_FP4_REGNUM)
return builtin_type_uint64;
else
- return builtin_type_ieee_double_big;
+ return builtin_type_ieee_double;
}
/* Return non-zero if REGNUM is not a register available to the user
|| (regnum > HPPA_IPSW_REGNUM && regnum < HPPA_FP4_REGNUM));
}
+static int
+hppa32_cannot_fetch_register (int regnum)
+{
+ /* cr26 and cr27 are readable (but not writable) from userspace. */
+ if (regnum == HPPA_CR26_REGNUM || regnum == HPPA_CR27_REGNUM)
+ return 0;
+ else
+ return hppa32_cannot_store_register (regnum);
+}
+
static int
hppa64_cannot_store_register (int regnum)
{
|| (regnum > HPPA_IPSW_REGNUM && regnum < HPPA64_FP4_REGNUM));
}
+static int
+hppa64_cannot_fetch_register (int regnum)
+{
+ /* cr26 and cr27 are readable (but not writable) from userspace. */
+ if (regnum == HPPA_CR26_REGNUM || regnum == HPPA_CR27_REGNUM)
+ return 0;
+ else
+ return hppa64_cannot_store_register (regnum);
+}
+
static CORE_ADDR
hppa_smash_text_address (CORE_ADDR addr)
{
{
gdb_byte buf[HPPA_INSN_SIZE];
- deprecated_read_memory_nobpt (npc, buf, HPPA_INSN_SIZE);
+ read_memory_nobpt (npc, buf, HPPA_INSN_SIZE);
insn[i] = extract_unsigned_integer (buf, HPPA_INSN_SIZE);
if ((insn[i] & pattern[i].mask) == pattern[i].data)
npc += 4;
systems: $$dyncall, import stubs and PLT stubs. */
CORE_ADDR
-hppa_skip_trampoline_code (CORE_ADDR pc)
+hppa_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
{
unsigned int insn[HPPA_MAX_INSN_PATTERN_LEN];
int dp_rel;
/* $$dyncall handles both PLABELs and direct addresses. */
if (hppa_in_dyncall (pc))
{
- pc = read_register (HPPA_R0_REGNUM + 22);
+ pc = get_frame_register_unsigned (frame, HPPA_R0_REGNUM + 22);
/* PLABELs have bit 30 set; if it's a PLABEL, then dereference it. */
if (pc & 0x2)
pc = hppa_extract_21 (insn[0]) + hppa_extract_14 (insn[1]);
if (dp_rel)
- pc += read_register (HPPA_DP_REGNUM);
+ pc += get_frame_register_unsigned (frame, HPPA_DP_REGNUM);
else
- pc += read_register (HPPA_R0_REGNUM + 19);
+ pc += get_frame_register_unsigned (frame, HPPA_R0_REGNUM + 19);
/* fallthrough */
}
set_gdbarch_cannot_store_register (gdbarch,
hppa32_cannot_store_register);
set_gdbarch_cannot_fetch_register (gdbarch,
- hppa32_cannot_store_register);
+ hppa32_cannot_fetch_register);
break;
case 8:
set_gdbarch_num_regs (gdbarch, hppa64_num_regs);
set_gdbarch_cannot_store_register (gdbarch,
hppa64_cannot_store_register);
set_gdbarch_cannot_fetch_register (gdbarch,
- hppa64_cannot_store_register);
+ hppa64_cannot_fetch_register);
break;
default:
internal_error (__FILE__, __LINE__, _("Unsupported address size: %d"),
and LP64, but might show differences some day. */
set_gdbarch_long_long_bit (gdbarch, 64);
set_gdbarch_long_double_bit (gdbarch, 128);
- set_gdbarch_long_double_format (gdbarch, &floatformat_ia64_quad_big);
+ set_gdbarch_long_double_format (gdbarch, floatformats_ia64_quad);
/* The following gdbarch vector elements do not depend on the address
size, or in any other gdbarch element previously set. */