/* 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
+ Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
+ 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
Free Software Foundation, Inc.
Contributed by Alessandro Forin(af@cs.cmu.edu) at CMU
#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
{
floatformat_big, 128, 0, 1, 11, 1023, 2047, 12, 52,
floatformat_intbit_no,
- "floatformat_ieee_double_big",
+ "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)
{
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);
}
{
/* The floating-point registers raw, or cooked, always match
mips_isa_regsize(), and also map 1:1, byte for byte. */
- switch (gdbarch_byte_order (gdbarch))
- {
- case BFD_ENDIAN_BIG:
- if (mips_isa_regsize (gdbarch) == 4)
- return builtin_type_ieee_single_big;
- else
- return builtin_type_ieee_double_big;
- case BFD_ENDIAN_LITTLE:
- if (mips_isa_regsize (gdbarch) == 4)
- return builtin_type_ieee_single_little;
- else
- return builtin_type_ieee_double_little;
- case BFD_ENDIAN_UNKNOWN:
- default:
- internal_error (__FILE__, __LINE__, _("bad switch"));
- }
+ if (mips_isa_regsize (gdbarch) == 4)
+ return builtin_type_ieee_single;
+ else
+ return builtin_type_ieee_double;
}
else if (regnum < NUM_REGS)
{
}
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);
{
struct mips_frame_cache *info = mips_insn16_frame_cache (next_frame,
this_cache);
- (*this_id) = frame_id_build (info->base, frame_func_unwind (next_frame));
+ (*this_id) = frame_id_build (info->base,
+ frame_func_unwind (next_frame, NORMAL_FRAME));
}
static void
static const struct frame_unwind *
mips_insn16_frame_sniffer (struct frame_info *next_frame)
{
- CORE_ADDR pc = frame_pc_unwind (next_frame);
+ CORE_ADDR pc = frame_unwind_address_in_block (next_frame, NORMAL_FRAME);
if (mips_pc_is_mips16 (pc))
return &mips_insn16_frame_unwind;
return NULL;
{
struct mips_frame_cache *info = mips_insn32_frame_cache (next_frame,
this_cache);
- (*this_id) = frame_id_build (info->base, frame_func_unwind (next_frame));
+ (*this_id) = frame_id_build (info->base,
+ frame_func_unwind (next_frame, NORMAL_FRAME));
}
static void
static const struct frame_unwind *
mips_insn32_frame_sniffer (struct frame_info *next_frame)
{
- CORE_ADDR pc = frame_pc_unwind (next_frame);
+ CORE_ADDR pc = frame_unwind_address_in_block (next_frame, NORMAL_FRAME);
if (! mips_pc_is_mips16 (pc))
return &mips_insn32_frame_unwind;
return NULL;
mips_stub_frame_sniffer (struct frame_info *next_frame)
{
struct obj_section *s;
- CORE_ADDR pc = frame_pc_unwind (next_frame);
+ CORE_ADDR pc = frame_unwind_address_in_block (next_frame, NORMAL_FRAME);
if (in_plt_section (pc, NULL))
return &mips_stub_frame_unwind;
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;
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 struct type *
mips_float_register_type (void)
{
- if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
- return builtin_type_ieee_single_big;
- else
- return builtin_type_ieee_single_little;
+ return builtin_type_ieee_single;
}
static struct type *
mips_double_register_type (void)
{
- if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
- return builtin_type_ieee_double_big;
- else
- return builtin_type_ieee_double_little;
+ return builtin_type_ieee_double;
}
/* Copy a 32-bit single-precision value from the current frame
gdb_byte raw_buffer[MAX_REGISTER_SIZE];
int offset;
- if (TYPE_CODE (gdbarch_register_type (gdbarch, regnum)) == TYPE_CODE_FLT)
+ if (TYPE_CODE (register_type (gdbarch, regnum)) == TYPE_CODE_FLT)
{
mips_print_fp_register (file, frame, regnum);
return;
offset = 0;
print_scalar_formatted (raw_buffer + offset,
- gdbarch_register_type (gdbarch, regnum), 'x', 0,
+ register_type (gdbarch, regnum), 'x', 0,
file);
}
{
if (*REGISTER_NAME (regnum) == '\0')
continue; /* unused register */
- if (TYPE_CODE (gdbarch_register_type (gdbarch, regnum)) ==
+ if (TYPE_CODE (register_type (gdbarch, regnum)) ==
TYPE_CODE_FLT)
break; /* end the row: reached FP register */
if (col == 0)
{
if (*REGISTER_NAME (regnum) == '\0')
continue; /* unused register */
- if (TYPE_CODE (gdbarch_register_type (gdbarch, regnum)) ==
+ if (TYPE_CODE (register_type (gdbarch, regnum)) ==
TYPE_CODE_FLT)
break; /* end row: reached FP register */
/* OK: get the data in raw format. */
regnum = NUM_REGS;
while (regnum < NUM_REGS + NUM_PSEUDO_REGS)
{
- if (TYPE_CODE (gdbarch_register_type (gdbarch, regnum)) ==
+ if (TYPE_CODE (register_type (gdbarch, regnum)) ==
TYPE_CODE_FLT)
{
if (all) /* true for "INFO ALL-REGISTERS" command */
}
-/* 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 gdb_byte *buf)
{
- 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,
- TYPE_LENGTH (builtin_type_void_data_ptr));
+ return (CORE_ADDR) extract_signed_integer (buf, TYPE_LENGTH (type));
}
static 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)
{
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);
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,
- &floatformat_n32n64_long_double_big);
+ set_gdbarch_long_double_format (gdbarch, floatformats_n32n64_long);
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,
- &floatformat_n32n64_long_double_big);
+ set_gdbarch_long_double_format (gdbarch, floatformats_n32n64_long);
break;
default:
internal_error (__FILE__, __LINE__, _("unknown ABI in switch"));
set_gdbarch_single_step_through_delay (gdbarch, mips_single_step_through_delay);
+ /* Virtual tables. */
+ set_gdbarch_vbit_in_delta (gdbarch, 1);
+
+ mips_register_g_packet_guesses (gdbarch);
+
/* Hook in OS ABI-specific overrides, if they have been registered. */
gdbarch_init_osabi (info, gdbarch);