* mips-tdep.c (make_mips16_addr): New function.

(mips_elf_make_msymbol_special): Don't set the low bit in the
	symbol's address.
	(mips_read_pc, mips_unwind_pc, mips_addr_bits_remove): Strip bit
	indicating mips16 address, if present.
	(mips_write_pc): Set bit indicating mips16 address when in a mips16
	function.
	(mips_eabi_push_dummy_call, mips_o64_push_dummy_call): Likewise,
	but for each function pointer argument to inferior function call.
This commit is contained in:
Kevin Buettner 2010-12-17 21:39:27 +00:00
parent 900c7f9d20
commit 930bd0e01a
2 changed files with 68 additions and 5 deletions

View file

@ -1,3 +1,15 @@
2010-12-17 Kevin Buettner <kevinb@redhat.com>
* mips-tdep.c (make_mips16_addr): New function.
(mips_elf_make_msymbol_special): Don't set the low bit in the
symbol's address.
(mips_read_pc, mips_unwind_pc, mips_addr_bits_remove): Strip bit
indicating mips16 address, if present.
(mips_write_pc): Set bit indicating mips16 address when in a mips16
function.
(mips_eabi_push_dummy_call, mips_o64_push_dummy_call): Likewise,
but for each function pointer argument to inferior function call.
2010-12-17 Tom Tromey <tromey@redhat.com>
* psympriv.h (struct partial_symtab) <readin>: Move field

View file

@ -205,6 +205,12 @@ unmake_mips16_addr (CORE_ADDR addr)
return ((addr) & ~(CORE_ADDR) 1);
}
static CORE_ADDR
make_mips16_addr (CORE_ADDR addr)
{
return ((addr) | (CORE_ADDR) 1);
}
/* Return the MIPS ABI associated with GDBARCH. */
enum mips_abi
mips_abi (struct gdbarch *gdbarch)
@ -264,7 +270,6 @@ mips_elf_make_msymbol_special (asymbol * sym, struct minimal_symbol *msym)
if (((elf_symbol_type *) (sym))->internal_elf_sym.st_other == STO_MIPS16)
{
MSYMBOL_TARGET_FLAG_1 (msym) = 1;
SYMBOL_VALUE_ADDRESS (msym) |= 1;
}
}
@ -931,14 +936,21 @@ mips_read_pc (struct regcache *regcache)
ULONGEST pc;
int regnum = mips_regnum (get_regcache_arch (regcache))->pc;
regcache_cooked_read_signed (regcache, regnum, &pc);
if (is_mips16_addr (pc))
pc = unmake_mips16_addr (pc);
return pc;
}
static CORE_ADDR
mips_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
{
return frame_unwind_register_signed
(next_frame, gdbarch_num_regs (gdbarch) + mips_regnum (gdbarch)->pc);
ULONGEST pc;
pc = frame_unwind_register_signed
(next_frame, gdbarch_num_regs (gdbarch) + mips_regnum (gdbarch)->pc);
if (is_mips16_addr (pc))
pc = unmake_mips16_addr (pc);
return pc;
}
static CORE_ADDR
@ -967,7 +979,10 @@ static void
mips_write_pc (struct regcache *regcache, CORE_ADDR pc)
{
int regnum = mips_regnum (get_regcache_arch (regcache))->pc;
regcache_cooked_write_unsigned (regcache, regnum, pc);
if (mips_pc_is_mips16 (pc))
regcache_cooked_write_unsigned (regcache, regnum, make_mips16_addr (pc));
else
regcache_cooked_write_unsigned (regcache, regnum, pc);
}
/* Fetch and return instruction from the specified location. If the PC
@ -2450,6 +2465,10 @@ static CORE_ADDR
mips_addr_bits_remove (struct gdbarch *gdbarch, CORE_ADDR addr)
{
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
if (is_mips16_addr (addr))
addr = unmake_mips16_addr (addr);
if (mips_mask_address_p (tdep) && (((ULONGEST) addr) >> 32 == 0xffffffffUL))
/* This hack is a work-around for existing boards using PMON, the
simulator, and any other 64-bit targets that doesn't have true
@ -2869,9 +2888,25 @@ mips_eabi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
"mips_eabi_push_dummy_call: %d len=%d type=%d",
argnum + 1, len, (int) typecode);
/* Function pointer arguments to mips16 code need to be made into
mips16 pointers. */
if (typecode == TYPE_CODE_PTR
&& TYPE_CODE (TYPE_TARGET_TYPE (arg_type)) == TYPE_CODE_FUNC)
{
CORE_ADDR addr = extract_signed_integer (value_contents (arg),
len, byte_order);
if (mips_pc_is_mips16 (addr))
{
store_signed_integer (valbuf, len, byte_order,
make_mips16_addr (addr));
val = valbuf;
}
else
val = value_contents (arg);
}
/* The EABI passes structures that do not fit in a register by
reference. */
if (len > regsize
else if (len > regsize
&& (typecode == TYPE_CODE_STRUCT || typecode == TYPE_CODE_UNION))
{
store_unsigned_integer (valbuf, regsize, byte_order,
@ -4159,6 +4194,7 @@ mips_o64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
for (argnum = 0; argnum < nargs; argnum++)
{
const gdb_byte *val;
gdb_byte valbuf[MAX_REGISTER_SIZE];
struct value *arg = args[argnum];
struct type *arg_type = check_typedef (value_type (arg));
int len = TYPE_LENGTH (arg_type);
@ -4171,6 +4207,21 @@ mips_o64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
val = value_contents (arg);
/* Function pointer arguments to mips16 code need to be made into
mips16 pointers. */
if (typecode == TYPE_CODE_PTR
&& TYPE_CODE (TYPE_TARGET_TYPE (arg_type)) == TYPE_CODE_FUNC)
{
CORE_ADDR addr = extract_signed_integer (value_contents (arg),
len, byte_order);
if (mips_pc_is_mips16 (addr))
{
store_signed_integer (valbuf, len, byte_order,
make_mips16_addr (addr));
val = valbuf;
}
}
/* Floating point arguments passed in registers have to be
treated specially. On 32-bit architectures, doubles
are passed in register pairs; the even register gets