/* Target-dependent code for the MIPS architecture, for GDB, the GNU Debugger.
- Copyright 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996,
- 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software
- Foundation, Inc.
+ Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996,
+ 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+ Free Software Foundation, Inc.
Contributed by Alessandro Forin(af@cs.cmu.edu) at CMU
and by Per Bothner(bothner@cs.wisc.edu) at U.Wisconsin.
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., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
+ Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
#include "defs.h"
#include "gdb_string.h"
static int
n32n64_floatformat_always_valid (const struct floatformat *fmt,
- const char *from)
+ const void *from)
{
return 1;
}
static CORE_ADDR
unmake_mips16_addr (CORE_ADDR addr)
{
- return ((addr) & ~1);
+ return ((addr) & ~(CORE_ADDR) 1);
}
/* Return the contents of register REGNUM as a signed integer. */
static void
mips_xfer_register (struct regcache *regcache, int reg_num, int length,
- enum bfd_endian endian, bfd_byte * in,
- const bfd_byte * out, int buf_offset)
+ enum bfd_endian endian, gdb_byte *in,
+ const gdb_byte *out, int buf_offset)
{
int reg_offset = 0;
gdb_assert (reg_num >= NUM_REGS);
static void
mips_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
- int cookednum, void *buf)
+ int cookednum, gdb_byte *buf)
{
int rawnum = cookednum % NUM_REGS;
gdb_assert (cookednum >= NUM_REGS && cookednum < 2 * NUM_REGS);
static void
mips_pseudo_register_write (struct gdbarch *gdbarch,
struct regcache *regcache, int cookednum,
- const void *buf)
+ const gdb_byte *buf)
{
int rawnum = cookednum % NUM_REGS;
gdb_assert (cookednum >= NUM_REGS && cookednum < 2 * NUM_REGS);
static void
mips_register_to_value (struct frame_info *frame, int regnum,
- struct type *type, void *to)
+ struct type *type, gdb_byte *to)
{
- get_frame_register (frame, regnum + 0, (char *) to + 4);
- get_frame_register (frame, regnum + 1, (char *) to + 0);
+ get_frame_register (frame, regnum + 0, to + 4);
+ get_frame_register (frame, regnum + 1, to + 0);
}
static void
mips_value_to_register (struct frame_info *frame, int regnum,
- struct type *type, const void *from)
+ struct type *type, const gdb_byte *from)
{
- put_frame_register (frame, regnum + 0, (const char *) from + 4);
- put_frame_register (frame, regnum + 1, (const char *) from + 0);
+ put_frame_register (frame, regnum + 0, from + 4);
+ put_frame_register (frame, regnum + 1, from + 0);
}
/* Return the GDB type object for the "standard" data type of data in
static ULONGEST
mips_fetch_instruction (CORE_ADDR addr)
{
- char buf[MIPS_INSN32_SIZE];
+ gdb_byte buf[MIPS_INSN32_SIZE];
int instlen;
int status;
unsigned long reg;
reg = jtype_target (inst) << 2;
/* Upper four bits get never changed... */
- pc = reg + ((pc + 4) & 0xf0000000);
+ pc = reg + ((pc + 4) & ~(CORE_ADDR) 0x0fffffff);
}
break;
/* FIXME case JALX : */
{
unsigned long reg;
reg = jtype_target (inst) << 2;
- pc = reg + ((pc + 4) & 0xf0000000) + 1; /* yes, +1 */
+ pc = reg + ((pc + 4) & ~(CORE_ADDR) 0x0fffffff) + 1; /* yes, +1 */
/* Add 1 to indicate 16 bit mode - Invert ISA mode */
}
break; /* The new PC will be alternate mode */
static unsigned int
fetch_mips_16 (CORE_ADDR pc)
{
- char buf[8];
+ gdb_byte buf[8];
pc &= 0xfffffffe; /* clear the low order bit */
target_read_memory (pc, buf, 2);
return extract_unsigned_integer (buf, 2);
static CORE_ADDR
add_offset_16 (CORE_ADDR pc, int offset)
{
- return ((offset << 2) | ((pc + 2) & (0xf0000000)));
+ return ((offset << 2) | ((pc + 2) & (~(CORE_ADDR) 0x0fffffff)));
}
static CORE_ADDR
void **this_cache,
int regnum, int *optimizedp,
enum lval_type *lvalp, CORE_ADDR *addrp,
- int *realnump, void *valuep)
+ int *realnump, gdb_byte *valuep)
{
struct mips_frame_cache *info = mips_insn16_frame_cache (next_frame,
this_cache);
void **this_cache,
int regnum, int *optimizedp,
enum lval_type *lvalp, CORE_ADDR *addrp,
- int *realnump, void *valuep)
+ int *realnump, gdb_byte *valuep)
{
struct mips_frame_cache *info = mips_insn32_frame_cache (next_frame,
this_cache);
void **this_cache,
int regnum, int *optimizedp,
enum lval_type *lvalp, CORE_ADDR *addrp,
- int *realnump, void *valuep)
+ int *realnump, gdb_byte *valuep)
{
struct trad_frame_cache *this_trad_cache
= mips_stub_frame_cache (next_frame, this_cache);
static const struct frame_unwind *
mips_stub_frame_sniffer (struct frame_info *next_frame)
{
+ struct obj_section *s;
CORE_ADDR pc = frame_pc_unwind (next_frame);
+
if (in_plt_section (pc, NULL))
return &mips_stub_frame_unwind;
- else
- return NULL;
+
+ /* 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 NULL;
}
static CORE_ADDR
from first to last. */
for (argnum = 0; argnum < nargs; argnum++)
{
- char *val;
- char valbuf[MAX_REGISTER_SIZE];
+ 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);
fprintf_unfiltered (gdb_stdlog, " push");
}
else
- val = (char *) value_contents (arg);
+ val = value_contents (arg);
/* 32-bit ABIs always start floating point arguments in an
even-numbered floating point register. Round the FP register
static enum return_value_convention
mips_eabi_return_value (struct gdbarch *gdbarch,
struct type *type, struct regcache *regcache,
- void *readbuf, const void *writebuf)
+ gdb_byte *readbuf, const gdb_byte *writebuf)
{
if (TYPE_LENGTH (type) > 2 * mips_abi_regsize (gdbarch))
return RETURN_VALUE_STRUCT_CONVENTION;
from first to last. */
for (argnum = 0; argnum < nargs; argnum++)
{
- char *val;
+ const gdb_byte *val;
struct value *arg = args[argnum];
struct type *arg_type = check_typedef (value_type (arg));
int len = TYPE_LENGTH (arg_type);
"mips_n32n64_push_dummy_call: %d len=%d type=%d",
argnum + 1, len, (int) typecode);
- val = (char *) value_contents (arg);
+ val = value_contents (arg);
if (fp_register_arg_p (typecode, arg_type)
&& float_argreg <= MIPS_LAST_FP_ARG_REGNUM)
static enum return_value_convention
mips_n32n64_return_value (struct gdbarch *gdbarch,
struct type *type, struct regcache *regcache,
- void *readbuf, const void *writebuf)
+ gdb_byte *readbuf, const gdb_byte *writebuf)
{
struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
if (TYPE_CODE (type) == TYPE_CODE_STRUCT
|| TYPE_CODE (type) == TYPE_CODE_ARRAY
|| TYPE_LENGTH (type) > 2 * mips_abi_regsize (gdbarch))
return RETURN_VALUE_STRUCT_CONVENTION;
+ else if (TYPE_CODE (type) == TYPE_CODE_FLT
+ && TYPE_LENGTH (type) == 16
+ && tdep->mips_fpu_type != MIPS_FPU_NONE)
+ {
+ /* A 128-bit floating-point value fills both $f0 and $f2. The
+ two registers are used in the same as memory order, so the
+ eight bytes with the lower memory address are in $f0. */
+ if (mips_debug)
+ fprintf_unfiltered (gdb_stderr, "Return float in $f0 and $f2\n");
+ mips_xfer_register (regcache,
+ NUM_REGS + mips_regnum (current_gdbarch)->fp0,
+ 8, TARGET_BYTE_ORDER, readbuf, writebuf, 0);
+ mips_xfer_register (regcache,
+ NUM_REGS + mips_regnum (current_gdbarch)->fp0 + 2,
+ 8, TARGET_BYTE_ORDER, readbuf ? readbuf + 8 : readbuf,
+ writebuf ? writebuf + 8 : writebuf, 0);
+ return RETURN_VALUE_REGISTER_CONVENTION;
+ }
else if (TYPE_CODE (type) == TYPE_CODE_FLT
&& tdep->mips_fpu_type != MIPS_FPU_NONE)
{
from first to last. */
for (argnum = 0; argnum < nargs; argnum++)
{
- char *val;
+ const gdb_byte *val;
struct value *arg = args[argnum];
struct type *arg_type = check_typedef (value_type (arg));
int len = TYPE_LENGTH (arg_type);
"mips_o32_push_dummy_call: %d len=%d type=%d",
argnum + 1, len, (int) typecode);
- val = (char *) value_contents (arg);
+ val = value_contents (arg);
/* 32-bit ABIs always start floating point arguments in an
even-numbered floating point register. Round the FP register
static enum return_value_convention
mips_o32_return_value (struct gdbarch *gdbarch, struct type *type,
struct regcache *regcache,
- void *readbuf, const void *writebuf)
+ gdb_byte *readbuf, const gdb_byte *writebuf)
{
struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
/* A struct that contains one or two floats. Each value is part
in the least significant part of their floating point
register.. */
- bfd_byte reg[MAX_REGISTER_SIZE];
+ gdb_byte reg[MAX_REGISTER_SIZE];
int regnum;
int field;
for (field = 0, regnum = mips_regnum (current_gdbarch)->fp0;
from first to last. */
for (argnum = 0; argnum < nargs; argnum++)
{
- char *val;
+ const gdb_byte *val;
struct value *arg = args[argnum];
struct type *arg_type = check_typedef (value_type (arg));
int len = TYPE_LENGTH (arg_type);
"mips_o64_push_dummy_call: %d len=%d type=%d",
argnum + 1, len, (int) typecode);
- val = (char *) value_contents (arg);
+ val = value_contents (arg);
/* 32-bit ABIs always start floating point arguments in an
even-numbered floating point register. Round the FP register
static enum return_value_convention
mips_o64_return_value (struct gdbarch *gdbarch,
struct type *type, struct regcache *regcache,
- void *readbuf, const void *writebuf)
+ gdb_byte *readbuf, const gdb_byte *writebuf)
{
return RETURN_VALUE_STRUCT_CONVENTION;
}
static void
mips_read_fp_register_single (struct frame_info *frame, int regno,
- char *rare_buffer)
+ gdb_byte *rare_buffer)
{
int raw_size = register_size (current_gdbarch, regno);
- char *raw_buffer = alloca (raw_size);
+ gdb_byte *raw_buffer = alloca (raw_size);
if (!frame_register_read (frame, regno, raw_buffer))
error (_("can't read register %d (%s)"), regno, REGISTER_NAME (regno));
static void
mips_read_fp_register_double (struct frame_info *frame, int regno,
- char *rare_buffer)
+ gdb_byte *rare_buffer)
{
int raw_size = register_size (current_gdbarch, regno);
mips_print_fp_register (struct ui_file *file, struct frame_info *frame,
int regnum)
{ /* do values for FP (float) regs */
- char *raw_buffer;
+ gdb_byte *raw_buffer;
double doub, flt1; /* doubles extracted from raw hex data */
int inv1, inv2;
- raw_buffer =
- (char *) alloca (2 *
- register_size (current_gdbarch,
- mips_regnum (current_gdbarch)->fp0));
+ raw_buffer = alloca (2 * register_size (current_gdbarch,
+ mips_regnum (current_gdbarch)->fp0));
fprintf_filtered (file, "%s:", REGISTER_NAME (regnum));
fprintf_filtered (file, "%*s", 4 - (int) strlen (REGISTER_NAME (regnum)),
int regnum, int all)
{
struct gdbarch *gdbarch = get_frame_arch (frame);
- char raw_buffer[MAX_REGISTER_SIZE];
+ gdb_byte raw_buffer[MAX_REGISTER_SIZE];
int offset;
if (TYPE_CODE (gdbarch_register_type (gdbarch, regnum)) == TYPE_CODE_FLT)
{
struct gdbarch *gdbarch = get_frame_arch (frame);
/* do values for GP (int) regs */
- char raw_buffer[MAX_REGISTER_SIZE];
+ gdb_byte raw_buffer[MAX_REGISTER_SIZE];
int ncols = (mips_abi_regsize (gdbarch) == 8 ? 4 : 8); /* display cols per row */
int col, byte;
int regnum;
/* For GP registers, we print a separate row of names above the vals */
- fprintf_filtered (file, " ");
for (col = 0, regnum = start_regnum;
col < ncols && regnum < NUM_REGS + NUM_PSEUDO_REGS; regnum++)
{
if (TYPE_CODE (gdbarch_register_type (gdbarch, regnum)) ==
TYPE_CODE_FLT)
break; /* end the row: reached FP register */
+ if (col == 0)
+ fprintf_filtered (file, " ");
fprintf_filtered (file,
mips_abi_regsize (current_gdbarch) == 8 ? "%17s" : "%9s",
REGISTER_NAME (regnum));
col++;
}
+
+ if (col == 0)
+ return regnum;
+
/* print the R0 to R31 names */
if ((start_regnum % NUM_REGS) < MIPS_NUMREGS)
fprintf_filtered (file, "\n R%-4d", start_regnum % NUM_REGS);
register_size (current_gdbarch,
regnum) - register_size (current_gdbarch, regnum);
byte < register_size (current_gdbarch, regnum); byte++)
- fprintf_filtered (file, "%02x", (unsigned char) raw_buffer[byte]);
+ fprintf_filtered (file, "%02x", raw_buffer[byte]);
else
for (byte = register_size (current_gdbarch, regnum) - 1;
byte >= 0; byte--)
- fprintf_filtered (file, "%02x", (unsigned char) raw_buffer[byte]);
+ fprintf_filtered (file, "%02x", raw_buffer[byte]);
fprintf_filtered (file, " ");
col++;
}
struct frame_info *frame)
{
CORE_ADDR pc = get_frame_pc (frame);
- char buf[MIPS_INSN32_SIZE];
+ gdb_byte buf[MIPS_INSN32_SIZE];
/* There is no branch delay slot on MIPS16. */
if (mips_pc_is_mips16 (pc))
return 0;
+ if (!breakpoint_here_p (pc + 4))
+ return 0;
+
if (!safe_frame_unwind_memory (frame, pc, buf, sizeof buf))
/* If error reading memory, guess that it is not a delayed
branch. */
(if necessary) to point to the actual memory location where the
breakpoint should be inserted. */
-static const unsigned char *
+static const gdb_byte *
mips_breakpoint_from_pc (CORE_ADDR *pcptr, int *lenptr)
{
if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
{
if (mips_pc_is_mips16 (*pcptr))
{
- static unsigned char mips16_big_breakpoint[] = { 0xe8, 0xa5 };
+ static gdb_byte mips16_big_breakpoint[] = { 0xe8, 0xa5 };
*pcptr = unmake_mips16_addr (*pcptr);
*lenptr = sizeof (mips16_big_breakpoint);
return mips16_big_breakpoint;
/* The IDT board uses an unusual breakpoint value, and
sometimes gets confused when it sees the usual MIPS
breakpoint instruction. */
- static unsigned char big_breakpoint[] = { 0, 0x5, 0, 0xd };
- static unsigned char pmon_big_breakpoint[] = { 0, 0, 0, 0xd };
- static unsigned char idt_big_breakpoint[] = { 0, 0, 0x0a, 0xd };
+ static gdb_byte big_breakpoint[] = { 0, 0x5, 0, 0xd };
+ static gdb_byte pmon_big_breakpoint[] = { 0, 0, 0, 0xd };
+ static gdb_byte idt_big_breakpoint[] = { 0, 0, 0x0a, 0xd };
*lenptr = sizeof (big_breakpoint);
{
if (mips_pc_is_mips16 (*pcptr))
{
- static unsigned char mips16_little_breakpoint[] = { 0xa5, 0xe8 };
+ static gdb_byte mips16_little_breakpoint[] = { 0xa5, 0xe8 };
*pcptr = unmake_mips16_addr (*pcptr);
*lenptr = sizeof (mips16_little_breakpoint);
return mips16_little_breakpoint;
}
else
{
- static unsigned char little_breakpoint[] = { 0xd, 0, 0x5, 0 };
- static unsigned char pmon_little_breakpoint[] = { 0xd, 0, 0, 0 };
- static unsigned char idt_little_breakpoint[] = { 0xd, 0x0a, 0, 0 };
+ static gdb_byte little_breakpoint[] = { 0xd, 0, 0x5, 0 };
+ static gdb_byte pmon_little_breakpoint[] = { 0xd, 0, 0, 0 };
+ static gdb_byte idt_little_breakpoint[] = { 0xd, 0x0a, 0, 0 };
*lenptr = sizeof (little_breakpoint);
static CORE_ADDR
mips_integer_to_address (struct gdbarch *gdbarch,
- struct type *type, const bfd_byte *buf)
+ struct type *type, const gdb_byte *buf)
{
- char *tmp = alloca (TYPE_LENGTH (builtin_type_void_data_ptr));
+ gdb_byte *tmp = alloca (TYPE_LENGTH (builtin_type_void_data_ptr));
LONGEST val = unpack_long (type, buf);
store_signed_integer (tmp, TYPE_LENGTH (builtin_type_void_data_ptr), val);
return extract_signed_integer (tmp,
}
}
+ /* Default 64-bit objects to N64 instead of O32. */
+ if (found_abi == MIPS_ABI_UNKNOWN
+ && info.abfd != NULL
+ && bfd_get_flavour (info.abfd) == bfd_target_elf_flavour
+ && elf_elfheader (info.abfd)->e_ident[EI_CLASS] == ELFCLASS64)
+ found_abi = MIPS_ABI_N64;
+
if (gdbarch_debug)
fprintf_unfiltered (gdb_stdlog, "mips_gdbarch_init: found_abi = %d\n",
found_abi);
/* Print out which MIPS ABI is in use. */
static void
-show_mips_abi (char *ignore_args, int from_tty)
+show_mips_abi (struct ui_file *file,
+ int from_tty,
+ struct cmd_list_element *ignored_cmd,
+ const char *ignored_value)
{
if (gdbarch_bfd_arch_info (current_gdbarch)->arch != bfd_arch_mips)
- printf_filtered
- ("The MIPS ABI is unknown because the current architecture is not MIPS.\n");
+ fprintf_filtered
+ (file,
+ "The MIPS ABI is unknown because the current architecture "
+ "is not MIPS.\n");
else
{
enum mips_abi global_abi = global_mips_abi ();
const char *actual_abi_str = mips_abi_strings[actual_abi];
if (global_abi == MIPS_ABI_UNKNOWN)
- printf_filtered
- ("The MIPS ABI is set automatically (currently \"%s\").\n",
+ fprintf_filtered
+ (file,
+ "The MIPS ABI is set automatically (currently \"%s\").\n",
actual_abi_str);
else if (global_abi == actual_abi)
- printf_filtered
- ("The MIPS ABI is assumed to be \"%s\" (due to user setting).\n",
+ fprintf_filtered
+ (file,
+ "The MIPS ABI is assumed to be \"%s\" (due to user setting).\n",
actual_abi_str);
else
{
/* Probably shouldn't happen... */
- printf_filtered
- ("The (auto detected) MIPS ABI \"%s\" is in use even though the user setting was \"%s\".\n",
+ fprintf_filtered
+ (file,
+ "The (auto detected) MIPS ABI \"%s\" is in use even though the user setting was \"%s\".\n",
actual_abi_str, mips_abi_strings[global_abi]);
}
}
&setmipscmdlist, &showmipscmdlist);
/* Allow the user to override the ABI. */
- c = add_set_enum_cmd
- ("abi", class_obscure, mips_abi_strings, &mips_abi_string,
- "Set the ABI used by this program.\n"
- "This option can be set to one of:\n"
- " auto - the default ABI associated with the current binary\n"
- " o32\n"
- " o64\n" " n32\n" " n64\n" " eabi32\n" " eabi64", &setmipscmdlist);
- set_cmd_sfunc (c, mips_abi_update);
- add_cmd ("abi", class_obscure, show_mips_abi,
- _("Show ABI in use by MIPS target"), &showmipscmdlist);
+ add_setshow_enum_cmd ("abi", class_obscure, mips_abi_strings,
+ &mips_abi_string, _("\
+Set the MIPS ABI used by this program."), _("\
+Show the MIPS ABI used by this program."), _("\
+This option can be set to one of:\n\
+ auto - the default ABI associated with the current binary\n\
+ o32\n\
+ o64\n\
+ n32\n\
+ n64\n\
+ eabi32\n\
+ eabi64"),
+ mips_abi_update,
+ show_mips_abi,
+ &setmipscmdlist, &showmipscmdlist);
/* Let the user turn off floating point and set the fence post for
heuristic_proc_start. */