aboutsummaryrefslogtreecommitdiff
path: root/gdb/mips-tdep.c
diff options
context:
space:
mode:
authorKevin Buettner <kevinb@redhat.com>2010-12-17 21:39:27 +0000
committerKevin Buettner <kevinb@redhat.com>2010-12-17 21:39:27 +0000
commit930bd0e01a2f0c2e59578b6e94aa6925d52d6bed (patch)
tree55b2739180ae7422e9cf4613e2ec8b6f6544248b /gdb/mips-tdep.c
parent900c7f9d2037c1c4a4c9697c25053cafa405f84c (diff)
downloadgdb-930bd0e01a2f0c2e59578b6e94aa6925d52d6bed.zip
gdb-930bd0e01a2f0c2e59578b6e94aa6925d52d6bed.tar.gz
gdb-930bd0e01a2f0c2e59578b6e94aa6925d52d6bed.tar.bz2
* 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.
Diffstat (limited to 'gdb/mips-tdep.c')
-rw-r--r--gdb/mips-tdep.c61
1 files changed, 56 insertions, 5 deletions
diff --git a/gdb/mips-tdep.c b/gdb/mips-tdep.c
index 6b9c5f6..81f2d7d 100644
--- a/gdb/mips-tdep.c
+++ b/gdb/mips-tdep.c
@@ -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