/* Target-dependent code for the MIPS architecture, for GDB, the GNU Debugger.
Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
- 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
+ 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
Free Software Foundation, Inc.
Contributed by Alessandro Forin(af@cs.cmu.edu) at CMU
int register_size;
};
-static int
-n32n64_floatformat_always_valid (const struct floatformat *fmt,
- const void *from)
-{
- return 1;
-}
-
-/* FIXME: brobecker/2004-08-08: Long Double values are 128 bit long.
- They are implemented as a pair of 64bit doubles where the high
- part holds the result of the operation rounded to double, and
- the low double holds the difference between the exact result and
- the rounded result. So "high" + "low" contains the result with
- added precision. Unfortunately, the floatformat structure used
- by GDB is not powerful enough to describe this format. As a temporary
- measure, we define a 128bit floatformat that only uses the high part.
- We lose a bit of precision but that's probably the best we can do
- for now with the current infrastructure. */
-
-static const struct floatformat floatformat_n32n64_long_double_big =
-{
- floatformat_big, 128, 0, 1, 11, 1023, 2047, 12, 52,
- floatformat_intbit_no,
- "floatformat_n32n64_long_double_big",
- n32n64_floatformat_always_valid
-};
-
-static const struct floatformat *floatformats_n32n64_long[BFD_ENDIAN_UNKNOWN] =
-{
- &floatformat_n32n64_long_double_big,
- &floatformat_n32n64_long_double_big
-};
-
const struct mips_regnum *
mips_regnum (struct gdbarch *gdbarch)
{
/* Convert to/from a register and the corresponding memory value. */
static int
-mips_convert_register_p (int regnum, struct type *type)
-{
- return (gdbarch_byte_order (current_gdbarch) == BFD_ENDIAN_BIG
- && register_size (current_gdbarch, regnum) == 4
- && (regnum % gdbarch_num_regs (current_gdbarch))
- >= mips_regnum (current_gdbarch)->fp0
- && (regnum % gdbarch_num_regs (current_gdbarch))
- < mips_regnum (current_gdbarch)->fp0 + 32
+mips_convert_register_p (struct gdbarch *gdbarch, int regnum, struct type *type)
+{
+ return (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG
+ && register_size (gdbarch, regnum) == 4
+ && (regnum % gdbarch_num_regs (gdbarch))
+ >= mips_regnum (gdbarch)->fp0
+ && (regnum % gdbarch_num_regs (gdbarch))
+ < mips_regnum (gdbarch)->fp0 + 32
&& TYPE_CODE (type) == TYPE_CODE_FLT && TYPE_LENGTH (type) == 8);
}
(next_frame, gdbarch_num_regs (gdbarch) + MIPS_SP_REGNUM);
}
-/* Assuming NEXT_FRAME->prev is a dummy, return the frame ID of that
+/* Assuming THIS_FRAME is a dummy, return the frame ID of that
dummy frame. The frame ID's base needs to match the TOS value
saved by save_dummy_frame_tos(), and the PC match the dummy frame's
breakpoint. */
static struct frame_id
-mips_unwind_dummy_id (struct gdbarch *gdbarch, struct frame_info *next_frame)
+mips_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame)
{
return frame_id_build
- (frame_unwind_register_signed (next_frame,
- gdbarch_num_regs (gdbarch)
- + MIPS_SP_REGNUM),
- frame_pc_unwind (next_frame));
+ (get_frame_register_signed (this_frame,
+ gdbarch_num_regs (gdbarch)
+ + MIPS_SP_REGNUM),
+ get_frame_pc (this_frame));
}
static void
}
else
instlen = MIPS_INSN32_SIZE;
- status = read_memory_nobpt (addr, buf, instlen);
+ status = target_read_memory (addr, buf, instlen);
if (status)
memory_error (status, addr);
return extract_unsigned_integer (buf, instlen);
/* The EXT-I, EXT-ri nad EXT-I8 instructions all have the same format
- for the bits which make up the immediatate extension. */
+ for the bits which make up the immediate extension. */
static CORE_ADDR
extended_offset (unsigned int extension)
static CORE_ADDR
mips16_scan_prologue (CORE_ADDR start_pc, CORE_ADDR limit_pc,
- struct frame_info *next_frame,
+ struct frame_info *this_frame,
struct mips_frame_cache *this_cache)
{
CORE_ADDR cur_pc;
unsigned short prev_inst = 0; /* saved copy of previous instruction */
unsigned inst = 0; /* current instruction */
unsigned entry_inst = 0; /* the entry instruction */
+ unsigned save_inst = 0; /* the save instruction */
int reg, offset;
int extend_bytes = 0;
int prev_extend_bytes;
CORE_ADDR end_prologue_addr = 0;
- struct gdbarch *gdbarch = get_frame_arch (next_frame);
+ struct gdbarch *gdbarch = get_frame_arch (this_frame);
/* Can be called when there's no process, and hence when there's no
- NEXT_FRAME. */
- if (next_frame != NULL)
- sp = frame_unwind_register_signed (next_frame,
- gdbarch_num_regs (gdbarch)
- + MIPS_SP_REGNUM);
+ THIS_FRAME. */
+ if (this_frame != NULL)
+ sp = get_frame_register_signed (this_frame,
+ gdbarch_num_regs (gdbarch)
+ + MIPS_SP_REGNUM);
else
sp = 0;
else if ((inst & 0xf81f) == 0xe809
&& (inst & 0x700) != 0x700) /* entry */
entry_inst = inst; /* save for later processing */
+ else if ((inst & 0xff80) == 0x6480) /* save */
+ {
+ save_inst = inst; /* save for later processing */
+ if (prev_extend_bytes) /* extend */
+ save_inst |= prev_inst << 16;
+ }
else if ((inst & 0xf800) == 0x1800) /* jal(x) */
cur_pc += MIPS_INSN16_SIZE; /* 32-bit instruction */
else if ((inst & 0xff1c) == 0x6704) /* move reg,$a0-$a3 */
}
}
+ /* The SAVE instruction is similar to ENTRY, except that defined by the
+ MIPS16e ASE of the MIPS Architecture. Unlike with ENTRY though, the
+ size of the frame is specified as an immediate field of instruction
+ and an extended variation exists which lets additional registers and
+ frame space to be specified. The instruction always treats registers
+ as 32-bit so its usefulness for 64-bit ABIs is questionable. */
+ if (save_inst != 0 && mips_abi_regsize (gdbarch) == 4)
+ {
+ static int args_table[16] = {
+ 0, 0, 0, 0, 1, 1, 1, 1,
+ 2, 2, 2, 0, 3, 3, 4, -1,
+ };
+ static int astatic_table[16] = {
+ 0, 1, 2, 3, 0, 1, 2, 3,
+ 0, 1, 2, 4, 0, 1, 0, -1,
+ };
+ int aregs = (save_inst >> 16) & 0xf;
+ int xsregs = (save_inst >> 24) & 0x7;
+ int args = args_table[aregs];
+ int astatic = astatic_table[aregs];
+ long frame_size;
+
+ if (args < 0)
+ {
+ warning (_("Invalid number of argument registers encoded in SAVE."));
+ args = 0;
+ }
+ if (astatic < 0)
+ {
+ warning (_("Invalid number of static registers encoded in SAVE."));
+ astatic = 0;
+ }
+
+ /* For standard SAVE the frame size of 0 means 128. */
+ frame_size = ((save_inst >> 16) & 0xf0) | (save_inst & 0xf);
+ if (frame_size == 0 && (save_inst >> 16) == 0)
+ frame_size = 16;
+ frame_size *= 8;
+ frame_offset += frame_size;
+
+ /* Now we can calculate what the SP must have been at the
+ start of the function prologue. */
+ sp += frame_offset;
+
+ /* Check if A0-A3 were saved in the caller's argument save area. */
+ for (reg = MIPS_A0_REGNUM, offset = 0; reg < args + 4; reg++)
+ {
+ set_reg_offset (this_cache, reg, sp + offset);
+ offset += mips_abi_regsize (gdbarch);
+ }
+
+ offset = -4;
+
+ /* Check if the RA register was pushed on the stack. */
+ if (save_inst & 0x40)
+ {
+ set_reg_offset (this_cache, MIPS_RA_REGNUM, sp + offset);
+ offset -= mips_abi_regsize (gdbarch);
+ }
+
+ /* Check if the S8 register was pushed on the stack. */
+ if (xsregs > 6)
+ {
+ set_reg_offset (this_cache, 30, sp + offset);
+ offset -= mips_abi_regsize (gdbarch);
+ xsregs--;
+ }
+ /* Check if S2-S7 were pushed on the stack. */
+ for (reg = 18 + xsregs - 1; reg > 18 - 1; reg--)
+ {
+ set_reg_offset (this_cache, reg, sp + offset);
+ offset -= mips_abi_regsize (gdbarch);
+ }
+
+ /* Check if the S1 register was pushed on the stack. */
+ if (save_inst & 0x10)
+ {
+ set_reg_offset (this_cache, 17, sp + offset);
+ offset -= mips_abi_regsize (gdbarch);
+ }
+ /* Check if the S0 register was pushed on the stack. */
+ if (save_inst & 0x20)
+ {
+ set_reg_offset (this_cache, 16, sp + offset);
+ offset -= mips_abi_regsize (gdbarch);
+ }
+
+ /* Check if A0-A3 were pushed on the stack. */
+ for (reg = MIPS_A0_REGNUM + 3; reg > MIPS_A0_REGNUM + 3 - astatic; reg--)
+ {
+ set_reg_offset (this_cache, reg, sp + offset);
+ offset -= mips_abi_regsize (gdbarch);
+ }
+ }
+
if (this_cache != NULL)
{
this_cache->base =
- (frame_unwind_register_signed (next_frame,
- gdbarch_num_regs (gdbarch) + frame_reg)
+ (get_frame_register_signed (this_frame,
+ gdbarch_num_regs (gdbarch) + frame_reg)
+ frame_offset - frame_adjust);
/* FIXME: brobecker/2004-10-10: Just as in the mips32 case, we should
be able to get rid of the assignment below, evetually. But it's
mips_insn32 unwinder. */
static struct mips_frame_cache *
-mips_insn16_frame_cache (struct frame_info *next_frame, void **this_cache)
+mips_insn16_frame_cache (struct frame_info *this_frame, void **this_cache)
{
struct mips_frame_cache *cache;
return (*this_cache);
cache = FRAME_OBSTACK_ZALLOC (struct mips_frame_cache);
(*this_cache) = cache;
- cache->saved_regs = trad_frame_alloc_saved_regs (next_frame);
+ cache->saved_regs = trad_frame_alloc_saved_regs (this_frame);
/* Analyze the function prologue. */
{
- const CORE_ADDR pc =
- frame_unwind_address_in_block (next_frame, NORMAL_FRAME);
+ const CORE_ADDR pc = get_frame_address_in_block (this_frame);
CORE_ADDR start_addr;
find_pc_partial_function (pc, NULL, &start_addr, NULL);
if (start_addr == 0)
return cache;
- mips16_scan_prologue (start_addr, pc, next_frame, *this_cache);
+ mips16_scan_prologue (start_addr, pc, this_frame, *this_cache);
}
/* gdbarch_sp_regnum contains the value and not the address. */
trad_frame_set_value (cache->saved_regs,
- gdbarch_num_regs (get_frame_arch (next_frame))
- + MIPS_SP_REGNUM,
+ gdbarch_num_regs (get_frame_arch (this_frame))
+ + MIPS_SP_REGNUM,
cache->base);
return (*this_cache);
}
static void
-mips_insn16_frame_this_id (struct frame_info *next_frame, void **this_cache,
+mips_insn16_frame_this_id (struct frame_info *this_frame, void **this_cache,
struct frame_id *this_id)
{
- struct mips_frame_cache *info = mips_insn16_frame_cache (next_frame,
+ struct mips_frame_cache *info = mips_insn16_frame_cache (this_frame,
this_cache);
- (*this_id) = frame_id_build (info->base,
- frame_func_unwind (next_frame, NORMAL_FRAME));
+ (*this_id) = frame_id_build (info->base, get_frame_func (this_frame));
}
-static void
-mips_insn16_frame_prev_register (struct frame_info *next_frame,
- void **this_cache,
- int regnum, int *optimizedp,
- enum lval_type *lvalp, CORE_ADDR *addrp,
- int *realnump, gdb_byte *valuep)
+static struct value *
+mips_insn16_frame_prev_register (struct frame_info *this_frame,
+ void **this_cache, int regnum)
{
- struct mips_frame_cache *info = mips_insn16_frame_cache (next_frame,
+ struct mips_frame_cache *info = mips_insn16_frame_cache (this_frame,
this_cache);
- trad_frame_get_prev_register (next_frame, info->saved_regs, regnum,
- optimizedp, lvalp, addrp, realnump, valuep);
+ return trad_frame_get_prev_register (this_frame, info->saved_regs, regnum);
+}
+
+static int
+mips_insn16_frame_sniffer (const struct frame_unwind *self,
+ struct frame_info *this_frame, void **this_cache)
+{
+ CORE_ADDR pc = get_frame_pc (this_frame);
+ if (mips_pc_is_mips16 (pc))
+ return 1;
+ return 0;
}
static const struct frame_unwind mips_insn16_frame_unwind =
{
NORMAL_FRAME,
mips_insn16_frame_this_id,
- mips_insn16_frame_prev_register
+ mips_insn16_frame_prev_register,
+ NULL,
+ mips_insn16_frame_sniffer
};
-static const struct frame_unwind *
-mips_insn16_frame_sniffer (struct frame_info *next_frame)
-{
- CORE_ADDR pc = frame_pc_unwind (next_frame);
- if (mips_pc_is_mips16 (pc))
- return &mips_insn16_frame_unwind;
- return NULL;
-}
-
static CORE_ADDR
-mips_insn16_frame_base_address (struct frame_info *next_frame,
+mips_insn16_frame_base_address (struct frame_info *this_frame,
void **this_cache)
{
- struct mips_frame_cache *info = mips_insn16_frame_cache (next_frame,
+ struct mips_frame_cache *info = mips_insn16_frame_cache (this_frame,
this_cache);
return info->base;
}
};
static const struct frame_base *
-mips_insn16_frame_base_sniffer (struct frame_info *next_frame)
+mips_insn16_frame_base_sniffer (struct frame_info *this_frame)
{
- if (mips_insn16_frame_sniffer (next_frame) != NULL)
+ CORE_ADDR pc = get_frame_pc (this_frame);
+ if (mips_pc_is_mips16 (pc))
return &mips_insn16_frame_base;
else
return NULL;
static CORE_ADDR
mips32_scan_prologue (CORE_ADDR start_pc, CORE_ADDR limit_pc,
- struct frame_info *next_frame,
+ struct frame_info *this_frame,
struct mips_frame_cache *this_cache)
{
CORE_ADDR cur_pc;
CORE_ADDR end_prologue_addr = 0;
int seen_sp_adjust = 0;
int load_immediate_bytes = 0;
- struct gdbarch *gdbarch = get_frame_arch (next_frame);
+ struct gdbarch *gdbarch = get_frame_arch (this_frame);
+ int regsize_is_64_bits = (mips_abi_regsize (gdbarch) == 8);
/* Can be called when there's no process, and hence when there's no
- NEXT_FRAME. */
- if (next_frame != NULL)
- sp = frame_unwind_register_signed (next_frame,
- gdbarch_num_regs (gdbarch)
- + MIPS_SP_REGNUM);
+ THIS_FRAME. */
+ if (this_frame != NULL)
+ sp = get_frame_register_signed (this_frame,
+ gdbarch_num_regs (gdbarch)
+ + MIPS_SP_REGNUM);
else
sp = 0;
break;
seen_sp_adjust = 1;
}
- else if ((high_word & 0xFFE0) == 0xafa0) /* sw reg,offset($sp) */
+ else if (((high_word & 0xFFE0) == 0xafa0) /* sw reg,offset($sp) */
+ && !regsize_is_64_bits)
{
set_reg_offset (this_cache, reg, sp + low_word);
}
- else if ((high_word & 0xFFE0) == 0xffa0) /* sd reg,offset($sp) */
+ else if (((high_word & 0xFFE0) == 0xffa0) /* sd reg,offset($sp) */
+ && regsize_is_64_bits)
{
/* Irix 6.2 N32 ABI uses sd instructions for saving $gp and $ra. */
set_reg_offset (this_cache, reg, sp + low_word);
/* Old gcc frame, r30 is virtual frame pointer. */
if ((long) low_word != frame_offset)
frame_addr = sp + low_word;
- else if (next_frame && frame_reg == MIPS_SP_REGNUM)
+ else if (this_frame && frame_reg == MIPS_SP_REGNUM)
{
unsigned alloca_adjust;
frame_reg = 30;
- frame_addr = frame_unwind_register_signed
- (next_frame, gdbarch_num_regs (gdbarch) + 30);
+ frame_addr = get_frame_register_signed
+ (this_frame, gdbarch_num_regs (gdbarch) + 30);
alloca_adjust = (unsigned) (frame_addr - (sp + low_word));
if (alloca_adjust > 0)
else if (inst == 0x03A0F021 || inst == 0x03a0f025 || inst == 0x03a0f02d)
{
/* New gcc frame, virtual frame pointer is at r30 + frame_size. */
- if (next_frame && frame_reg == MIPS_SP_REGNUM)
+ if (this_frame && frame_reg == MIPS_SP_REGNUM)
{
unsigned alloca_adjust;
frame_reg = 30;
- frame_addr = frame_unwind_register_signed
- (next_frame, gdbarch_num_regs (gdbarch) + 30);
+ frame_addr = get_frame_register_signed
+ (this_frame, gdbarch_num_regs (gdbarch) + 30);
alloca_adjust = (unsigned) (frame_addr - sp);
if (alloca_adjust > 0)
}
}
}
- else if ((high_word & 0xFFE0) == 0xafc0) /* sw reg,offset($30) */
+ else if ((high_word & 0xFFE0) == 0xafc0 /* sw reg,offset($30) */
+ && !regsize_is_64_bits)
{
set_reg_offset (this_cache, reg, frame_addr + low_word);
}
if (this_cache != NULL)
{
this_cache->base =
- (frame_unwind_register_signed (next_frame,
- gdbarch_num_regs (gdbarch) + frame_reg)
+ (get_frame_register_signed (this_frame,
+ gdbarch_num_regs (gdbarch) + frame_reg)
+ frame_offset);
/* FIXME: brobecker/2004-09-15: We should be able to get rid of
this assignment below, eventually. But it's still needed
unwinder. */
static struct mips_frame_cache *
-mips_insn32_frame_cache (struct frame_info *next_frame, void **this_cache)
+mips_insn32_frame_cache (struct frame_info *this_frame, void **this_cache)
{
struct mips_frame_cache *cache;
cache = FRAME_OBSTACK_ZALLOC (struct mips_frame_cache);
(*this_cache) = cache;
- cache->saved_regs = trad_frame_alloc_saved_regs (next_frame);
+ cache->saved_regs = trad_frame_alloc_saved_regs (this_frame);
/* Analyze the function prologue. */
{
- const CORE_ADDR pc =
- frame_unwind_address_in_block (next_frame, NORMAL_FRAME);
+ const CORE_ADDR pc = get_frame_address_in_block (this_frame);
CORE_ADDR start_addr;
find_pc_partial_function (pc, NULL, &start_addr, NULL);
if (start_addr == 0)
return cache;
- mips32_scan_prologue (start_addr, pc, next_frame, *this_cache);
+ mips32_scan_prologue (start_addr, pc, this_frame, *this_cache);
}
/* gdbarch_sp_regnum contains the value and not the address. */
trad_frame_set_value (cache->saved_regs,
- gdbarch_num_regs (get_frame_arch (next_frame))
- + MIPS_SP_REGNUM,
+ gdbarch_num_regs (get_frame_arch (this_frame))
+ + MIPS_SP_REGNUM,
cache->base);
return (*this_cache);
}
static void
-mips_insn32_frame_this_id (struct frame_info *next_frame, void **this_cache,
+mips_insn32_frame_this_id (struct frame_info *this_frame, void **this_cache,
struct frame_id *this_id)
{
- struct mips_frame_cache *info = mips_insn32_frame_cache (next_frame,
+ struct mips_frame_cache *info = mips_insn32_frame_cache (this_frame,
this_cache);
- (*this_id) = frame_id_build (info->base,
- frame_func_unwind (next_frame, NORMAL_FRAME));
+ (*this_id) = frame_id_build (info->base, get_frame_func (this_frame));
}
-static void
-mips_insn32_frame_prev_register (struct frame_info *next_frame,
- void **this_cache,
- int regnum, int *optimizedp,
- enum lval_type *lvalp, CORE_ADDR *addrp,
- int *realnump, gdb_byte *valuep)
+static struct value *
+mips_insn32_frame_prev_register (struct frame_info *this_frame,
+ void **this_cache, int regnum)
{
- struct mips_frame_cache *info = mips_insn32_frame_cache (next_frame,
+ struct mips_frame_cache *info = mips_insn32_frame_cache (this_frame,
this_cache);
- trad_frame_get_prev_register (next_frame, info->saved_regs, regnum,
- optimizedp, lvalp, addrp, realnump, valuep);
+ return trad_frame_get_prev_register (this_frame, info->saved_regs, regnum);
+}
+
+static int
+mips_insn32_frame_sniffer (const struct frame_unwind *self,
+ struct frame_info *this_frame, void **this_cache)
+{
+ CORE_ADDR pc = get_frame_pc (this_frame);
+ if (! mips_pc_is_mips16 (pc))
+ return 1;
+ return 0;
}
static const struct frame_unwind mips_insn32_frame_unwind =
{
NORMAL_FRAME,
mips_insn32_frame_this_id,
- mips_insn32_frame_prev_register
+ mips_insn32_frame_prev_register,
+ NULL,
+ mips_insn32_frame_sniffer
};
-static const struct frame_unwind *
-mips_insn32_frame_sniffer (struct frame_info *next_frame)
-{
- CORE_ADDR pc = frame_pc_unwind (next_frame);
- if (! mips_pc_is_mips16 (pc))
- return &mips_insn32_frame_unwind;
- return NULL;
-}
-
static CORE_ADDR
-mips_insn32_frame_base_address (struct frame_info *next_frame,
+mips_insn32_frame_base_address (struct frame_info *this_frame,
void **this_cache)
{
- struct mips_frame_cache *info = mips_insn32_frame_cache (next_frame,
+ struct mips_frame_cache *info = mips_insn32_frame_cache (this_frame,
this_cache);
return info->base;
}
};
static const struct frame_base *
-mips_insn32_frame_base_sniffer (struct frame_info *next_frame)
+mips_insn32_frame_base_sniffer (struct frame_info *this_frame)
{
- if (mips_insn32_frame_sniffer (next_frame) != NULL)
+ CORE_ADDR pc = get_frame_pc (this_frame);
+ if (! mips_pc_is_mips16 (pc))
return &mips_insn32_frame_base;
else
return NULL;
}
static struct trad_frame_cache *
-mips_stub_frame_cache (struct frame_info *next_frame, void **this_cache)
+mips_stub_frame_cache (struct frame_info *this_frame, void **this_cache)
{
CORE_ADDR pc;
CORE_ADDR start_addr;
CORE_ADDR stack_addr;
struct trad_frame_cache *this_trad_cache;
- struct gdbarch *gdbarch = get_frame_arch (next_frame);
+ struct gdbarch *gdbarch = get_frame_arch (this_frame);
+ int num_regs = gdbarch_num_regs (gdbarch);
if ((*this_cache) != NULL)
return (*this_cache);
- this_trad_cache = trad_frame_cache_zalloc (next_frame);
+ this_trad_cache = trad_frame_cache_zalloc (this_frame);
(*this_cache) = this_trad_cache;
/* The return address is in the link register. */
trad_frame_set_reg_realreg (this_trad_cache,
gdbarch_pc_regnum (gdbarch),
- (gdbarch_num_regs (gdbarch) + MIPS_RA_REGNUM));
+ num_regs + MIPS_RA_REGNUM);
/* Frame ID, since it's a frameless / stackless function, no stack
space is allocated and SP on entry is the current SP. */
- pc = frame_pc_unwind (next_frame);
+ pc = get_frame_pc (this_frame);
find_pc_partial_function (pc, NULL, &start_addr, NULL);
- stack_addr = frame_unwind_register_signed (next_frame, MIPS_SP_REGNUM);
+ stack_addr = get_frame_register_signed (this_frame,
+ num_regs + MIPS_SP_REGNUM);
trad_frame_set_id (this_trad_cache, frame_id_build (stack_addr, start_addr));
/* Assume that the frame's base is the same as the
}
static void
-mips_stub_frame_this_id (struct frame_info *next_frame, void **this_cache,
+mips_stub_frame_this_id (struct frame_info *this_frame, void **this_cache,
struct frame_id *this_id)
{
struct trad_frame_cache *this_trad_cache
- = mips_stub_frame_cache (next_frame, this_cache);
+ = mips_stub_frame_cache (this_frame, this_cache);
trad_frame_get_id (this_trad_cache, this_id);
}
-static void
-mips_stub_frame_prev_register (struct frame_info *next_frame,
- void **this_cache,
- int regnum, int *optimizedp,
- enum lval_type *lvalp, CORE_ADDR *addrp,
- int *realnump, gdb_byte *valuep)
+static struct value *
+mips_stub_frame_prev_register (struct frame_info *this_frame,
+ void **this_cache, int regnum)
{
struct trad_frame_cache *this_trad_cache
- = mips_stub_frame_cache (next_frame, this_cache);
- trad_frame_get_register (this_trad_cache, next_frame, regnum, optimizedp,
- lvalp, addrp, realnump, valuep);
+ = mips_stub_frame_cache (this_frame, this_cache);
+ return trad_frame_get_register (this_trad_cache, this_frame, regnum);
}
-static const struct frame_unwind mips_stub_frame_unwind =
-{
- NORMAL_FRAME,
- mips_stub_frame_this_id,
- mips_stub_frame_prev_register
-};
-
-static const struct frame_unwind *
-mips_stub_frame_sniffer (struct frame_info *next_frame)
+static int
+mips_stub_frame_sniffer (const struct frame_unwind *self,
+ struct frame_info *this_frame, void **this_cache)
{
gdb_byte dummy[4];
struct obj_section *s;
- CORE_ADDR pc = frame_unwind_address_in_block (next_frame, NORMAL_FRAME);
+ CORE_ADDR pc = get_frame_address_in_block (this_frame);
/* Use the stub unwinder for unreadable code. */
- if (target_read_memory (frame_pc_unwind (next_frame), dummy, 4) != 0)
- return &mips_stub_frame_unwind;
+ if (target_read_memory (get_frame_pc (this_frame), dummy, 4) != 0)
+ return 1;
if (in_plt_section (pc, NULL))
- return &mips_stub_frame_unwind;
+ return 1;
/* Binutils for MIPS puts lazy resolution stubs into .MIPS.stubs. */
s = find_pc_section (pc);
if (s != NULL
&& strcmp (bfd_get_section_name (s->objfile->obfd, s->the_bfd_section),
".MIPS.stubs") == 0)
- return &mips_stub_frame_unwind;
+ return 1;
- return NULL;
+ return 0;
}
+static const struct frame_unwind mips_stub_frame_unwind =
+{
+ NORMAL_FRAME,
+ mips_stub_frame_this_id,
+ mips_stub_frame_prev_register,
+ NULL,
+ mips_stub_frame_sniffer
+};
+
static CORE_ADDR
-mips_stub_frame_base_address (struct frame_info *next_frame,
+mips_stub_frame_base_address (struct frame_info *this_frame,
void **this_cache)
{
struct trad_frame_cache *this_trad_cache
- = mips_stub_frame_cache (next_frame, this_cache);
+ = mips_stub_frame_cache (this_frame, this_cache);
return trad_frame_get_this_base (this_trad_cache);
}
};
static const struct frame_base *
-mips_stub_frame_base_sniffer (struct frame_info *next_frame)
+mips_stub_frame_base_sniffer (struct frame_info *this_frame)
{
- if (mips_stub_frame_sniffer (next_frame) != NULL)
+ if (mips_stub_frame_sniffer (&mips_stub_frame_unwind, this_frame, NULL))
return &mips_stub_frame_base;
else
return NULL;
/* Determine the return value convention being used. */
static enum return_value_convention
-mips_eabi_return_value (struct gdbarch *gdbarch,
+mips_eabi_return_value (struct gdbarch *gdbarch, struct type *func_type,
struct type *type, struct regcache *regcache,
gdb_byte *readbuf, const gdb_byte *writebuf)
{
purpose register. */
if (argreg <= MIPS_LAST_ARG_REGNUM)
{
- LONGEST regval =
- extract_unsigned_integer (val, partial_len);
+ LONGEST regval;
+
+ /* Sign extend pointers, 32-bit integers and signed
+ 16-bit and 8-bit integers; everything else is taken
+ as is. */
+
+ if ((partial_len == 4
+ && (typecode == TYPE_CODE_PTR
+ || typecode == TYPE_CODE_INT))
+ || (partial_len < 4
+ && typecode == TYPE_CODE_INT
+ && !TYPE_UNSIGNED (arg_type)))
+ regval = extract_signed_integer (val, partial_len);
+ else
+ regval = extract_unsigned_integer (val, partial_len);
/* A non-floating-point argument being passed in a
general register. If a struct or union, and if
}
static enum return_value_convention
-mips_n32n64_return_value (struct gdbarch *gdbarch,
+mips_n32n64_return_value (struct gdbarch *gdbarch, struct type *func_type,
struct type *type, struct regcache *regcache,
gdb_byte *readbuf, const gdb_byte *writebuf)
{
}
static enum return_value_convention
-mips_o32_return_value (struct gdbarch *gdbarch, struct type *type,
- struct regcache *regcache,
+mips_o32_return_value (struct gdbarch *gdbarch, struct type *func_type,
+ struct type *type, struct regcache *regcache,
gdb_byte *readbuf, const gdb_byte *writebuf)
{
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
}
static enum return_value_convention
-mips_o64_return_value (struct gdbarch *gdbarch,
+mips_o64_return_value (struct gdbarch *gdbarch, struct type *func_type,
struct type *type, struct regcache *regcache,
gdb_byte *readbuf, const gdb_byte *writebuf)
{
delay slot of a non-prologue instruction). */
static CORE_ADDR
-mips_skip_prologue (CORE_ADDR pc)
+mips_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
{
CORE_ADDR limit_pc;
CORE_ADDR func_addr;
show_mipsfpu_command (char *args, int from_tty)
{
char *fpu;
+
+ if (gdbarch_bfd_arch_info (current_gdbarch)->arch != bfd_arch_mips)
+ {
+ printf_unfiltered
+ ("The MIPS floating-point coprocessor is unknown "
+ "because the current architecture is not MIPS.\n");
+ return;
+ }
+
switch (MIPS_FPU_TYPE)
{
case MIPS_FPU_SINGLE:
info->disassembler_options = "gpr-names=32";
/* Call the appropriate disassembler based on the target endian-ness. */
- if (gdbarch_byte_order (current_gdbarch) == BFD_ENDIAN_BIG)
+ if (info->endian == BFD_ENDIAN_BIG)
return print_insn_big_mips (memaddr, info);
else
return print_insn_little_mips (memaddr, info);
should be inserted. */
static const gdb_byte *
-mips_breakpoint_from_pc (CORE_ADDR *pcptr, int *lenptr)
+mips_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr, int *lenptr)
{
- if (gdbarch_byte_order (current_gdbarch) == BFD_ENDIAN_BIG)
+ if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
{
if (mips_pc_is_mips16 (*pcptr))
{
[1 * gdbarch_num_regs .. 2 * gdbarch_num_regs) REGNUM. */
static int
-mips_stab_reg_to_regnum (int num)
+mips_stab_reg_to_regnum (struct gdbarch *gdbarch, int num)
{
int regnum;
if (num >= 0 && num < 32)
regnum = num;
else if (num >= 38 && num < 70)
- regnum = num + mips_regnum (current_gdbarch)->fp0 - 38;
+ regnum = num + mips_regnum (gdbarch)->fp0 - 38;
else if (num == 70)
- regnum = mips_regnum (current_gdbarch)->hi;
+ regnum = mips_regnum (gdbarch)->hi;
else if (num == 71)
- regnum = mips_regnum (current_gdbarch)->lo;
+ regnum = mips_regnum (gdbarch)->lo;
else
/* This will hopefully (eventually) provoke a warning. Should
we be calling complaint() here? */
- return gdbarch_num_regs (current_gdbarch)
- + gdbarch_num_pseudo_regs (current_gdbarch);
- return gdbarch_num_regs (current_gdbarch) + regnum;
+ return gdbarch_num_regs (gdbarch) + gdbarch_num_pseudo_regs (gdbarch);
+ return gdbarch_num_regs (gdbarch) + regnum;
}
gdbarch_num_regs .. 2 * gdbarch_num_regs) REGNUM. */
static int
-mips_dwarf_dwarf2_ecoff_reg_to_regnum (int num)
+mips_dwarf_dwarf2_ecoff_reg_to_regnum (struct gdbarch *gdbarch, int num)
{
int regnum;
if (num >= 0 && num < 32)
regnum = num;
else if (num >= 32 && num < 64)
- regnum = num + mips_regnum (current_gdbarch)->fp0 - 32;
+ regnum = num + mips_regnum (gdbarch)->fp0 - 32;
else if (num == 64)
- regnum = mips_regnum (current_gdbarch)->hi;
+ regnum = mips_regnum (gdbarch)->hi;
else if (num == 65)
- regnum = mips_regnum (current_gdbarch)->lo;
+ regnum = mips_regnum (gdbarch)->lo;
else
/* This will hopefully (eventually) provoke a warning. Should we
be calling complaint() here? */
- return gdbarch_num_regs (current_gdbarch)
- + gdbarch_num_pseudo_regs (current_gdbarch);
- return gdbarch_num_regs (current_gdbarch) + regnum;
+ return gdbarch_num_regs (gdbarch) + gdbarch_num_pseudo_regs (gdbarch);
+ return gdbarch_num_regs (gdbarch) + regnum;
}
static int
-mips_register_sim_regno (int regnum)
+mips_register_sim_regno (struct gdbarch *gdbarch, int regnum)
{
/* Only makes sense to supply raw registers. */
- gdb_assert (regnum >= 0 && regnum < gdbarch_num_regs (current_gdbarch));
+ gdb_assert (regnum >= 0 && regnum < gdbarch_num_regs (gdbarch));
/* FIXME: cagney/2002-05-13: Need to look at the pseudo register to
decide if it is valid. Should instead define a standard sim/gdb
register numbering scheme. */
- if (gdbarch_register_name (current_gdbarch,
- gdbarch_num_regs
- (current_gdbarch) + regnum) != NULL
- && gdbarch_register_name (current_gdbarch,
- gdbarch_num_regs
- (current_gdbarch) + regnum)[0] != '\0')
+ if (gdbarch_register_name (gdbarch,
+ gdbarch_num_regs (gdbarch) + regnum) != NULL
+ && gdbarch_register_name (gdbarch,
+ gdbarch_num_regs (gdbarch) + regnum)[0] != '\0')
return regnum;
else
return LEGACY_SIM_REGNO_IGNORE;
an assertion failure. */
static void
-mips_virtual_frame_pointer (CORE_ADDR pc, int *reg, LONGEST *offset)
+mips_virtual_frame_pointer (struct gdbarch *gdbarch,
+ CORE_ADDR pc, int *reg, LONGEST *offset)
{
*reg = MIPS_SP_REGNUM;
*offset = 0;
set_gdbarch_ptr_bit (gdbarch, 32);
set_gdbarch_long_long_bit (gdbarch, 64);
set_gdbarch_long_double_bit (gdbarch, 128);
- set_gdbarch_long_double_format (gdbarch, floatformats_n32n64_long);
+ set_gdbarch_long_double_format (gdbarch, floatformats_ibm_long_double);
break;
case MIPS_ABI_N64:
set_gdbarch_push_dummy_call (gdbarch, mips_n32n64_push_dummy_call);
set_gdbarch_ptr_bit (gdbarch, 64);
set_gdbarch_long_long_bit (gdbarch, 64);
set_gdbarch_long_double_bit (gdbarch, 128);
- set_gdbarch_long_double_format (gdbarch, floatformats_n32n64_long);
+ set_gdbarch_long_double_format (gdbarch, floatformats_ibm_long_double);
break;
default:
internal_error (__FILE__, __LINE__, _("unknown ABI in switch"));
/* Unwind the frame. */
set_gdbarch_unwind_pc (gdbarch, mips_unwind_pc);
set_gdbarch_unwind_sp (gdbarch, mips_unwind_sp);
- set_gdbarch_unwind_dummy_id (gdbarch, mips_unwind_dummy_id);
+ set_gdbarch_dummy_id (gdbarch, mips_dummy_id);
/* Map debug register numbers onto internal register numbers. */
set_gdbarch_stab_reg_to_regnum (gdbarch, mips_stab_reg_to_regnum);
gdbarch_init_osabi (info, gdbarch);
/* Unwind the frame. */
- frame_unwind_append_sniffer (gdbarch, dwarf2_frame_sniffer);
- frame_unwind_append_sniffer (gdbarch, mips_stub_frame_sniffer);
- frame_unwind_append_sniffer (gdbarch, mips_insn16_frame_sniffer);
- frame_unwind_append_sniffer (gdbarch, mips_insn32_frame_sniffer);
+ dwarf2_append_unwinders (gdbarch);
+ frame_unwind_append_unwinder (gdbarch, &mips_stub_frame_unwind);
+ frame_unwind_append_unwinder (gdbarch, &mips_insn16_frame_unwind);
+ frame_unwind_append_unwinder (gdbarch, &mips_insn32_frame_unwind);
frame_base_append_sniffer (gdbarch, dwarf2_frame_base_sniffer);
frame_base_append_sniffer (gdbarch, mips_stub_frame_base_sniffer);
frame_base_append_sniffer (gdbarch, mips_insn16_frame_base_sniffer);