/* 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.
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"
#include "trad-frame.h"
#include "infcall.h"
#include "floatformat.h"
+#include "remote.h"
+#include "target-descriptions.h"
static const struct objfile_data *mips_pdr_data;
static int mips_debug = 0;
+/* Properties (for struct target_desc) describing the g/G packet
+ layout. */
+#define PROPERTY_GP32 "internal: transfers-32bit-registers"
+#define PROPERTY_GP64 "internal: transfers-64bit-registers"
+
/* MIPS specific per-architecture information */
struct gdbarch_tdep
{
const struct mips_regnum *regnum;
/* Register names table for the current register set. */
const char **mips_processor_reg_names;
+
+ /* The size of register data available from the target, if known.
+ This doesn't quite obsolete the manual
+ mips64_transfers_32bit_regs_p, since that is documented to force
+ left alignment even for big endian (very strange). */
+ int register_size_valid_p;
+ int register_size;
};
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. */
int
mips_isa_regsize (struct gdbarch *gdbarch)
{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+ /* If we know how big the registers are, use that size. */
+ if (tdep->register_size_valid_p)
+ return tdep->register_size;
+
+ /* Fall back to the previous behavior. */
return (gdbarch_bfd_arch_info (gdbarch)->bits_per_word
/ gdbarch_bfd_arch_info (gdbarch)->bits_per_byte);
}
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;
}
else
instlen = MIPS_INSN32_SIZE;
- status = deprecated_read_memory_nobpt (addr, buf, instlen);
+ status = read_memory_nobpt (addr, buf, instlen);
if (status)
memory_error (status, addr);
return extract_unsigned_integer (buf, instlen);
return ((itype_immediate (inst) ^ 0x8000) - 0x8000) << 2;
}
-/* Determine whate to set a single step breakpoint while considering
- branch prediction */
+/* Determine where to set a single step breakpoint while considering
+ branch prediction. */
static CORE_ADDR
mips32_next_pc (CORE_ADDR pc)
{
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);
void
mips_software_single_step (enum target_signal sig, int insert_breakpoints_p)
{
- static CORE_ADDR next_pc;
- typedef char binsn_quantum[BREAKPOINT_MAX];
- static binsn_quantum break_mem;
- CORE_ADDR pc;
+ CORE_ADDR pc, next_pc;
if (insert_breakpoints_p)
{
pc = read_register (mips_regnum (current_gdbarch)->pc);
next_pc = mips_next_pc (pc);
- target_insert_breakpoint (next_pc, break_mem);
+ insert_single_step_breakpoint (next_pc);
}
else
- target_remove_breakpoint (next_pc, break_mem);
+ remove_single_step_breakpoints ();
}
/* Test whether the PC points to the return instruction at the
/* According to the current ABI, should the type be passed in a
floating-point register (assuming that there is space)? When there
- is no FPU, FP are not even considered as possibile candidates for
+ is no FPU, FP are not even considered as possible candidates for
FP registers and, consequently this returns false - forces FP
arguments into integer registers. */
&& (typecode == TYPE_CODE_STRUCT
|| typecode == TYPE_CODE_UNION)
&& TYPE_NFIELDS (arg_type) == 1
- && TYPE_CODE (TYPE_FIELD_TYPE (arg_type, 0)) == TYPE_CODE_FLT))
+ && TYPE_CODE (check_typedef (TYPE_FIELD_TYPE (arg_type, 0)))
+ == TYPE_CODE_FLT))
&& MIPS_FPU_TYPE != MIPS_FPU_NONE);
}
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
if (fp_register_arg_p (typecode, arg_type)
&& float_argreg <= MIPS_LAST_FP_ARG_REGNUM)
{
- if (mips_abi_regsize (gdbarch) < 8 && len == 8)
+ if (register_size (gdbarch, float_argreg) < 8 && len == 8)
{
int low_offset = TARGET_BYTE_ORDER == BFD_ENDIAN_BIG ? 4 : 0;
unsigned long regval;
return sp;
}
-/* Determin the return value convention being used. */
+/* Determine the return value convention being used. */
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
if (fp_register_arg_p (typecode, arg_type)
&& float_argreg <= MIPS_LAST_FP_ARG_REGNUM)
{
- if (mips_abi_regsize (gdbarch) < 8 && len == 8)
+ if (register_size (gdbarch, float_argreg) < 8 && len == 8)
{
int low_offset = TARGET_BYTE_ORDER == BFD_ENDIAN_BIG ? 4 : 0;
unsigned long regval;
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
big endian targets.
It does not seem to be necessary to do the
- same for integral types.
-
- Also don't do this adjustment on O64 binaries.
-
- cagney/2001-07-23: gdb/179: Also, GCC, when
- outputting LE O32 with sizeof (struct) <
- mips_abi_regsize(), generates a left shift as
- part of storing the argument in a register a
- register (the left shift isn't generated when
- sizeof (struct) >= mips_abi_regsize()). Since
- it is quite possible that this is GCC
- contradicting the LE/O32 ABI, GDB has not been
- adjusted to accommodate this. Either someone
- needs to demonstrate that the LE/O32 ABI
- specifies such a left shift OR this new ABI gets
- identified as such and GDB gets tweaked
- accordingly. */
+ same for integral types. */
- if (mips_abi_regsize (gdbarch) < 8
- && TARGET_BYTE_ORDER == BFD_ENDIAN_BIG
+ if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG
&& partial_len < mips_abi_regsize (gdbarch)
&& (typecode == TYPE_CODE_STRUCT ||
typecode == TYPE_CODE_UNION))
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;
+ struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+
+ if (TYPE_CODE (type) == TYPE_CODE_STRUCT
+ || TYPE_CODE (type) == TYPE_CODE_UNION
+ || TYPE_CODE (type) == TYPE_CODE_ARRAY)
+ return RETURN_VALUE_STRUCT_CONVENTION;
+ else if (fp_register_arg_p (TYPE_CODE (type), type))
+ {
+ /* A floating-point value. It fits in the least significant
+ part of FP0. */
+ if (mips_debug)
+ fprintf_unfiltered (gdb_stderr, "Return float in $fp0\n");
+ mips_xfer_register (regcache,
+ NUM_REGS + mips_regnum (current_gdbarch)->fp0,
+ TYPE_LENGTH (type),
+ TARGET_BYTE_ORDER, readbuf, writebuf, 0);
+ return RETURN_VALUE_REGISTER_CONVENTION;
+ }
+ else
+ {
+ /* A scalar extract each part but least-significant-byte
+ justified. */
+ int offset;
+ int regnum;
+ for (offset = 0, regnum = MIPS_V0_REGNUM;
+ offset < TYPE_LENGTH (type);
+ offset += mips_stack_argsize (gdbarch), regnum++)
+ {
+ int xfer = mips_stack_argsize (gdbarch);
+ if (offset + xfer > TYPE_LENGTH (type))
+ xfer = TYPE_LENGTH (type) - offset;
+ if (mips_debug)
+ fprintf_unfiltered (gdb_stderr, "Return scalar+%d:%d in $%d\n",
+ offset, xfer, regnum);
+ mips_xfer_register (regcache, NUM_REGS + regnum, xfer,
+ TARGET_BYTE_ORDER, readbuf, writebuf, offset);
+ }
+ return RETURN_VALUE_REGISTER_CONVENTION;
+ }
}
/* Floating point register management.
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))
(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);
}
-/* Convert an integer into an address. By first converting the value
- into a pointer and then extracting it signed, the address is
- guarenteed to be correctly sign extended. */
+/* Convert an integer into an address. Extracting the value signed
+ guarantees a correctly sign extended address. */
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));
- LONGEST val = unpack_long (type, buf);
- store_signed_integer (tmp, TYPE_LENGTH (builtin_type_void_data_ptr), val);
- return extract_signed_integer (tmp,
- TYPE_LENGTH (builtin_type_void_data_ptr));
+ return (CORE_ADDR) extract_signed_integer (buf, TYPE_LENGTH (type));
}
static void
warning (_("unsupported ABI %s."), name + 8);
}
+static void
+mips_find_long_section (bfd *abfd, asection *sect, void *obj)
+{
+ int *lbp = (int *) obj;
+ const char *name = bfd_get_section_name (abfd, sect);
+
+ if (strncmp (name, ".gcc_compiled_long32", 20) == 0)
+ *lbp = 32;
+ else if (strncmp (name, ".gcc_compiled_long64", 20) == 0)
+ *lbp = 64;
+ else if (strncmp (name, ".gcc_compiled_long", 18) == 0)
+ warning (_("unrecognized .gcc_compiled_longXX"));
+}
+
static enum mips_abi
global_mips_abi (void)
{
internal_error (__FILE__, __LINE__, _("unknown ABI string"));
}
+static void
+mips_register_g_packet_guesses (struct gdbarch *gdbarch)
+{
+ static struct target_desc *tdesc_gp32, *tdesc_gp64;
+
+ if (tdesc_gp32 == NULL)
+ {
+ /* Create feature sets with the appropriate properties. The values
+ are not important. */
+
+ tdesc_gp32 = allocate_target_description ();
+ set_tdesc_property (tdesc_gp32, PROPERTY_GP32, "");
+
+ tdesc_gp64 = allocate_target_description ();
+ set_tdesc_property (tdesc_gp64, PROPERTY_GP64, "");
+ }
+
+ /* If the size matches the set of 32-bit or 64-bit integer registers,
+ assume that's what we've got. */
+ register_remote_g_packet_guess (gdbarch, 38 * 4, tdesc_gp32);
+ register_remote_g_packet_guess (gdbarch, 38 * 8, tdesc_gp64);
+
+ /* If the size matches the full set of registers GDB traditionally
+ knows about, including floating point, for either 32-bit or
+ 64-bit, assume that's what we've got. */
+ register_remote_g_packet_guess (gdbarch, 90 * 4, tdesc_gp32);
+ register_remote_g_packet_guess (gdbarch, 90 * 8, tdesc_gp64);
+
+ /* Otherwise we don't have a useful guess. */
+}
+
static struct gdbarch *
mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
{
}
}
+ /* 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);
fprintf_unfiltered (gdb_stdlog,
"mips_gdbarch_init: fpu_type = %d\n", fpu_type);
+ /* Check for blatant incompatibilities. */
+
+ /* If we have only 32-bit registers, then we can't debug a 64-bit
+ ABI. */
+ if (info.target_desc
+ && tdesc_property (info.target_desc, PROPERTY_GP32) != NULL
+ && mips_abi != MIPS_ABI_EABI32
+ && mips_abi != MIPS_ABI_O32)
+ return NULL;
+
/* try to find a pre-existing architecture */
for (arches = gdbarch_list_lookup_by_info (arches, &info);
arches != NULL;
tdep->found_abi = found_abi;
tdep->mips_abi = mips_abi;
tdep->mips_fpu_type = fpu_type;
+ tdep->register_size_valid_p = 0;
+ tdep->register_size = 0;
+
+ if (info.target_desc)
+ {
+ /* Some useful properties can be inferred from the target. */
+ if (tdesc_property (info.target_desc, PROPERTY_GP32) != NULL)
+ {
+ tdep->register_size_valid_p = 1;
+ tdep->register_size = 4;
+ }
+ else if (tdesc_property (info.target_desc, PROPERTY_GP64) != NULL)
+ {
+ tdep->register_size_valid_p = 1;
+ tdep->register_size = 8;
+ }
+ }
/* Initially set everything according to the default ABI/ISA. */
set_gdbarch_short_bit (gdbarch, 16);
internal_error (__FILE__, __LINE__, _("unknown ABI in switch"));
}
+ /* GCC creates a pseudo-section whose name specifies the size of
+ longs, since -mlong32 or -mlong64 may be used independent of
+ other options. How those options affect pointer sizes is ABI and
+ architecture dependent, so use them to override the default sizes
+ set by the ABI. This table shows the relationship between ABI,
+ -mlongXX, and size of pointers:
+
+ ABI -mlongXX ptr bits
+ --- -------- --------
+ o32 32 32
+ o32 64 32
+ n32 32 32
+ n32 64 64
+ o64 32 32
+ o64 64 64
+ n64 32 32
+ n64 64 64
+ eabi32 32 32
+ eabi32 64 32
+ eabi64 32 32
+ eabi64 64 64
+
+ Note that for o32 and eabi32, pointers are always 32 bits
+ regardless of any -mlongXX option. For all others, pointers and
+ longs are the same, as set by -mlongXX or set by defaults.
+ */
+
+ if (info.abfd != NULL)
+ {
+ int long_bit = 0;
+
+ bfd_map_over_sections (info.abfd, mips_find_long_section, &long_bit);
+ if (long_bit)
+ {
+ set_gdbarch_long_bit (gdbarch, long_bit);
+ switch (mips_abi)
+ {
+ case MIPS_ABI_O32:
+ case MIPS_ABI_EABI32:
+ break;
+ case MIPS_ABI_N32:
+ case MIPS_ABI_O64:
+ case MIPS_ABI_N64:
+ case MIPS_ABI_EABI64:
+ set_gdbarch_ptr_bit (gdbarch, long_bit);
+ break;
+ default:
+ internal_error (__FILE__, __LINE__, _("unknown ABI in switch"));
+ }
+ }
+ }
+
/* FIXME: jlarmour/2000-04-07: There *is* a flag EF_MIPS_32BIT_MODE
that could indicate -gp32 BUT gas/config/tc-mips.c contains the
comment:
set_gdbarch_single_step_through_delay (gdbarch, mips_single_step_through_delay);
+ mips_register_g_packet_guesses (gdbarch);
+
/* Hook in OS ABI-specific overrides, if they have been registered. */
gdbarch_init_osabi (info, gdbarch);
{
int ef_mips_arch;
int ef_mips_32bitmode;
- /* determine the ISA */
+ /* Determine the ISA. */
switch (tdep->elf_flags & EF_MIPS_ARCH)
{
case E_MIPS_ARCH_1:
ef_mips_arch = 0;
break;
}
- /* determine the size of a pointer */
+ /* Determine the size of a pointer. */
ef_mips_32bitmode = (tdep->elf_flags & EF_MIPS_32BITMODE);
fprintf_unfiltered (file,
"mips_dump_tdep: tdep->elf_flags = 0x%x\n",