/* Target-dependent code for the MIPS architecture, for GDB, the GNU Debugger.
- Copyright (C) 1988-2017 Free Software Foundation, Inc.
+ Copyright (C) 1988-2019 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.
#include "user-regs.h"
#include "valprint.h"
#include "ax.h"
+#include "target-float.h"
#include <algorithm>
-static const struct objfile_data *mips_pdr_data;
-
static struct type *mips_register_type (struct gdbarch *gdbarch, int regnum);
static int mips32_instruction_has_delay_slot (struct gdbarch *gdbarch,
struct target_desc *mips_tdesc_gp32;
struct target_desc *mips_tdesc_gp64;
+/* The current set of options to be passed to the disassembler. */
+static char *mips_disassembler_options;
+
+/* Implicit disassembler options for individual ABIs. These tell
+ libopcodes to use general-purpose register names corresponding
+ to the ABI we have selected, perhaps via a `set mips abi ...'
+ override, rather than ones inferred from the ABI set in the ELF
+ headers of the binary file selected for debugging. */
+static const char mips_disassembler_options_o32[] = "gpr-names=32";
+static const char mips_disassembler_options_n32[] = "gpr-names=n32";
+static const char mips_disassembler_options_n64[] = "gpr-names=64";
+
const struct mips_regnum *
mips_regnum (struct gdbarch *gdbarch)
{
fprintf_unfiltered (gdb_stdlog, "%02x", out[buf_offset + i]);
}
if (in != NULL)
- regcache_cooked_read_part (regcache, reg_num, reg_offset, length,
- in + buf_offset);
+ regcache->cooked_read_part (reg_num, reg_offset, length, in + buf_offset);
if (out != NULL)
- regcache_cooked_write_part (regcache, reg_num, reg_offset, length,
- out + buf_offset);
+ regcache->cooked_write_part (reg_num, reg_offset, length, out + buf_offset);
if (mips_debug && in != NULL)
{
int i;
static CORE_ADDR heuristic_proc_start (struct gdbarch *, CORE_ADDR);
-static void reinit_frame_cache_sfunc (char *, int, struct cmd_list_element *);
-
/* The list of available "set mips " and "show mips " commands. */
static struct cmd_list_element *setmipscmdlist = NULL;
registers. Take care of alignment and size problems. */
static enum register_status
-mips_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
+mips_pseudo_register_read (struct gdbarch *gdbarch, readable_regcache *regcache,
int cookednum, gdb_byte *buf)
{
int rawnum = cookednum % gdbarch_num_regs (gdbarch);
gdb_assert (cookednum >= gdbarch_num_regs (gdbarch)
&& cookednum < 2 * gdbarch_num_regs (gdbarch));
if (register_size (gdbarch, rawnum) == register_size (gdbarch, cookednum))
- return regcache_raw_read (regcache, rawnum, buf);
+ return regcache->raw_read (rawnum, buf);
else if (register_size (gdbarch, rawnum) >
register_size (gdbarch, cookednum))
{
if (gdbarch_tdep (gdbarch)->mips64_transfers_32bit_regs_p)
- return regcache_raw_read_part (regcache, rawnum, 0, 4, buf);
+ return regcache->raw_read_part (rawnum, 0, 4, buf);
else
{
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
LONGEST regval;
enum register_status status;
- status = regcache_raw_read_signed (regcache, rawnum, ®val);
+ status = regcache->raw_read (rawnum, ®val);
if (status == REG_VALID)
store_signed_integer (buf, 4, byte_order, regval);
return status;
gdb_assert (cookednum >= gdbarch_num_regs (gdbarch)
&& cookednum < 2 * gdbarch_num_regs (gdbarch));
if (register_size (gdbarch, rawnum) == register_size (gdbarch, cookednum))
- regcache_raw_write (regcache, rawnum, buf);
+ regcache->raw_write (rawnum, buf);
else if (register_size (gdbarch, rawnum) >
register_size (gdbarch, cookednum))
{
if (gdbarch_tdep (gdbarch)->mips64_transfers_32bit_regs_p)
- regcache_raw_write_part (regcache, rawnum, 0, 4, buf);
+ regcache->raw_write_part (rawnum, 0, 4, buf);
else
{
/* Sign extend the shortened version of the register prior
register N. NOTE: This defines the pseudo register type so need to
rebuild the architecture vector. */
-static int mips64_transfers_32bit_regs_p = 0;
+static bool mips64_transfers_32bit_regs_p = false;
static void
-set_mips64_transfers_32bit_regs (char *args, int from_tty,
+set_mips64_transfers_32bit_regs (const char *args, int from_tty,
struct cmd_list_element *c)
{
struct gdbarch_info info;
}
/* Should the upper word of 64-bit addresses be zeroed? */
-enum auto_boolean mask_address_var = AUTO_BOOLEAN_AUTO;
+static enum auto_boolean mask_address_var = AUTO_BOOLEAN_AUTO;
static int
mips_mask_address_p (struct gdbarch_tdep *tdep)
all registers should be sign extended for simplicity? */
static CORE_ADDR
-mips_read_pc (struct regcache *regcache)
+mips_read_pc (readable_regcache *regcache)
{
int regnum = gdbarch_pc_regnum (regcache->arch ());
LONGEST pc;
- regcache_cooked_read_signed (regcache, regnum, &pc);
+ regcache->cooked_read (regnum, &pc);
return pc;
}
switch (micromips_op (insn >> 16))
{
case 0x00: /* POOL32A: bits 000000 */
- if (b0s6_op (insn) == 0x3c
- /* POOL32Axf: bits 000000 ... 111100 */
- && (b6s10_ext (insn) & 0x2bf) == 0x3c)
- /* JALR, JALR.HB: 000000 000x111100 111100 */
- /* JALRS, JALRS.HB: 000000 010x111100 111100 */
- pc = regcache_raw_get_signed (regcache, b0s5_reg (insn >> 16));
+ switch (b0s6_op (insn))
+ {
+ case 0x3c: /* POOL32Axf: bits 000000 ... 111100 */
+ switch (b6s10_ext (insn))
+ {
+ case 0x3c: /* JALR: 000000 0000111100 111100 */
+ case 0x7c: /* JALR.HB: 000000 0001111100 111100 */
+ case 0x13c: /* JALRS: 000000 0100111100 111100 */
+ case 0x17c: /* JALRS.HB: 000000 0101111100 111100 */
+ pc = regcache_raw_get_signed (regcache,
+ b0s5_reg (insn >> 16));
+ break;
+ case 0x22d: /* SYSCALL: 000000 1000101101 111100 */
+ {
+ struct gdbarch_tdep *tdep;
+
+ tdep = gdbarch_tdep (gdbarch);
+ if (tdep->syscall_next_pc != NULL)
+ pc = tdep->syscall_next_pc (get_current_frame ());
+ }
+ break;
+ }
+ break;
+ }
break;
case 0x10: /* POOL32I: bits 010000 */
struct frame_info *this_frame, void **this_cache)
{
gdb_byte dummy[4];
- struct obj_section *s;
CORE_ADDR pc = get_frame_address_in_block (this_frame);
struct bound_minimal_symbol msym;
stub. The stub for foo is named ".pic.foo". */
msym = lookup_minimal_symbol_by_pc (pc);
if (msym.minsym != NULL
- && MSYMBOL_LINKAGE_NAME (msym.minsym) != NULL
- && startswith (MSYMBOL_LINKAGE_NAME (msym.minsym), ".pic."))
+ && msym.minsym->linkage_name () != NULL
+ && startswith (msym.minsym->linkage_name (), ".pic."))
return 1;
return 0;
static std::vector<CORE_ADDR>
mips_deal_with_atomic_sequence (struct gdbarch *gdbarch, CORE_ADDR pc)
{
- CORE_ADDR breaks[2] = {-1, -1};
+ CORE_ADDR breaks[2] = {CORE_ADDR_MAX, CORE_ADDR_MAX};
CORE_ADDR loc = pc;
CORE_ADDR branch_bp; /* Breakpoint at branch instruction's destination. */
ULONGEST insn;
{
const int atomic_sequence_length = 16; /* Instruction sequence length. */
int last_breakpoint = 0; /* Defaults to 0 (no breakpoints placed). */
- CORE_ADDR breaks[2] = {-1, -1};
+ CORE_ADDR breaks[2] = {CORE_ADDR_MAX, CORE_ADDR_MAX};
CORE_ADDR branch_bp = 0; /* Breakpoint at branch instruction's
destination. */
CORE_ADDR loc = pc;
mips_eabi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
struct regcache *regcache, CORE_ADDR bp_addr,
int nargs, struct value **args, CORE_ADDR sp,
- int struct_return, CORE_ADDR struct_addr)
+ function_call_return_method return_method,
+ CORE_ADDR struct_addr)
{
int argreg;
int float_argreg;
int argnum;
- int len = 0;
+ int arg_space = 0;
int stack_offset = 0;
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
CORE_ADDR func_addr = find_function_addr (function, NULL);
than necessary for EABI, because the first few arguments are
passed in registers, but that's OK. */
for (argnum = 0; argnum < nargs; argnum++)
- len += align_up (TYPE_LENGTH (value_type (args[argnum])), abi_regsize);
- sp -= align_up (len, 16);
+ arg_space += align_up (TYPE_LENGTH (value_type (args[argnum])), abi_regsize);
+ sp -= align_up (arg_space, 16);
if (mips_debug)
fprintf_unfiltered (gdb_stdlog,
"mips_eabi_push_dummy_call: sp=%s allocated %ld\n",
- paddress (gdbarch, sp), (long) align_up (len, 16));
+ paddress (gdbarch, sp),
+ (long) align_up (arg_space, 16));
/* Initialize the integer and float register pointers. */
argreg = MIPS_A0_REGNUM;
float_argreg = mips_fpa0_regnum (gdbarch);
/* The struct_return pointer occupies the first parameter-passing reg. */
- if (struct_return)
+ if (return_method == return_method_struct)
{
if (mips_debug)
fprintf_unfiltered (gdb_stdlog,
mips_n32n64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
struct regcache *regcache, CORE_ADDR bp_addr,
int nargs, struct value **args, CORE_ADDR sp,
- int struct_return, CORE_ADDR struct_addr)
+ function_call_return_method return_method,
+ CORE_ADDR struct_addr)
{
int argreg;
int float_argreg;
int argnum;
- int len = 0;
+ int arg_space = 0;
int stack_offset = 0;
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
CORE_ADDR func_addr = find_function_addr (function, NULL);
/* Now make space on the stack for the args. */
for (argnum = 0; argnum < nargs; argnum++)
- len += align_up (TYPE_LENGTH (value_type (args[argnum])), MIPS64_REGSIZE);
- sp -= align_up (len, 16);
+ arg_space += align_up (TYPE_LENGTH (value_type (args[argnum])), MIPS64_REGSIZE);
+ sp -= align_up (arg_space, 16);
if (mips_debug)
fprintf_unfiltered (gdb_stdlog,
"mips_n32n64_push_dummy_call: sp=%s allocated %ld\n",
- paddress (gdbarch, sp), (long) align_up (len, 16));
+ paddress (gdbarch, sp),
+ (long) align_up (arg_space, 16));
/* Initialize the integer and float register pointers. */
argreg = MIPS_A0_REGNUM;
float_argreg = mips_fpa0_regnum (gdbarch);
/* The struct_return pointer occupies the first parameter-passing reg. */
- if (struct_return)
+ if (return_method == return_method_struct)
{
if (mips_debug)
fprintf_unfiltered (gdb_stdlog,
mips_o32_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
struct regcache *regcache, CORE_ADDR bp_addr,
int nargs, struct value **args, CORE_ADDR sp,
- int struct_return, CORE_ADDR struct_addr)
+ function_call_return_method return_method,
+ CORE_ADDR struct_addr)
{
int argreg;
int float_argreg;
int argnum;
- int len = 0;
+ int arg_space = 0;
int stack_offset = 0;
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
CORE_ADDR func_addr = find_function_addr (function, NULL);
/* Align to double-word if necessary. */
if (mips_type_needs_double_align (arg_type))
- len = align_up (len, MIPS32_REGSIZE * 2);
+ arg_space = align_up (arg_space, MIPS32_REGSIZE * 2);
/* Allocate space on the stack. */
- len += align_up (TYPE_LENGTH (arg_type), MIPS32_REGSIZE);
+ arg_space += align_up (TYPE_LENGTH (arg_type), MIPS32_REGSIZE);
}
- sp -= align_up (len, 16);
+ sp -= align_up (arg_space, 16);
if (mips_debug)
fprintf_unfiltered (gdb_stdlog,
"mips_o32_push_dummy_call: sp=%s allocated %ld\n",
- paddress (gdbarch, sp), (long) align_up (len, 16));
+ paddress (gdbarch, sp),
+ (long) align_up (arg_space, 16));
/* Initialize the integer and float register pointers. */
argreg = MIPS_A0_REGNUM;
float_argreg = mips_fpa0_regnum (gdbarch);
/* The struct_return pointer occupies the first parameter-passing reg. */
- if (struct_return)
+ if (return_method == return_method_struct)
{
if (mips_debug)
fprintf_unfiltered (gdb_stdlog,
struct regcache *regcache, CORE_ADDR bp_addr,
int nargs,
struct value **args, CORE_ADDR sp,
- int struct_return, CORE_ADDR struct_addr)
+ function_call_return_method return_method, CORE_ADDR struct_addr)
{
int argreg;
int float_argreg;
int argnum;
- int len = 0;
+ int arg_space = 0;
int stack_offset = 0;
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
CORE_ADDR func_addr = find_function_addr (function, NULL);
struct type *arg_type = check_typedef (value_type (args[argnum]));
/* Allocate space on the stack. */
- len += align_up (TYPE_LENGTH (arg_type), MIPS64_REGSIZE);
+ arg_space += align_up (TYPE_LENGTH (arg_type), MIPS64_REGSIZE);
}
- sp -= align_up (len, 16);
+ sp -= align_up (arg_space, 16);
if (mips_debug)
fprintf_unfiltered (gdb_stdlog,
"mips_o64_push_dummy_call: sp=%s allocated %ld\n",
- paddress (gdbarch, sp), (long) align_up (len, 16));
+ paddress (gdbarch, sp),
+ (long) align_up (arg_space, 16));
/* Initialize the integer and float register pointers. */
argreg = MIPS_A0_REGNUM;
float_argreg = mips_fpa0_regnum (gdbarch);
/* The struct_return pointer occupies the first parameter-passing reg. */
- if (struct_return)
+ if (return_method == return_method_struct)
{
if (mips_debug)
fprintf_unfiltered (gdb_stdlog,
{
CORE_ADDR func_addr = function ? find_function_addr (function, NULL) : 0;
int mips16 = mips_pc_is_mips16 (gdbarch, func_addr);
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
enum mips_fval_reg fval_reg;
fval_reg = readbuf ? mips16 ? mips_fval_gpr : mips_fval_fpr : mips_fval_both;
gdb_byte *raw_buffer;
std::string flt_str, dbl_str;
- const struct floatformat *flt_fmt
- = floatformat_from_type (builtin_type (gdbarch)->builtin_float);
- const struct floatformat *dbl_fmt
- = floatformat_from_type (builtin_type (gdbarch)->builtin_double);
+ const struct type *flt_type = builtin_type (gdbarch)->builtin_float;
+ const struct type *dbl_type = builtin_type (gdbarch)->builtin_double;
raw_buffer
= ((gdb_byte *)
/* 4-byte registers: Print hex and floating. Also print even
numbered registers as doubles. */
mips_read_fp_register_single (frame, regnum, raw_buffer);
- flt_str = floatformat_to_string (flt_fmt, raw_buffer, "%-17.9g");
+ flt_str = target_float_to_string (raw_buffer, flt_type, "%-17.9g");
get_formatted_print_options (&opts, 'x');
print_scalar_formatted (raw_buffer,
if ((regnum - gdbarch_num_regs (gdbarch)) % 2 == 0)
{
mips_read_fp_register_double (frame, regnum, raw_buffer);
- dbl_str = floatformat_to_string (dbl_fmt, raw_buffer, "%-24.17g");
+ dbl_str = target_float_to_string (raw_buffer, dbl_type, "%-24.17g");
fprintf_filtered (file, " dbl: %s", dbl_str.c_str ());
}
/* Eight byte registers: print each one as hex, float and double. */
mips_read_fp_register_single (frame, regnum, raw_buffer);
- flt_str = floatformat_to_string (flt_fmt, raw_buffer, "%-17.9g");
+ flt_str = target_float_to_string (raw_buffer, flt_type, "%-17.9g");
mips_read_fp_register_double (frame, regnum, raw_buffer);
- dbl_str = floatformat_to_string (dbl_fmt, raw_buffer, "%-24.17g");
+ dbl_str = target_float_to_string (raw_buffer, dbl_type, "%-24.17g");
get_formatted_print_options (&opts, 'x');
print_scalar_formatted (raw_buffer,
/* For GP registers, we print a separate row of names above the vals. */
for (col = 0, regnum = start_regnum;
- col < ncols && regnum < gdbarch_num_regs (gdbarch)
- + gdbarch_num_pseudo_regs (gdbarch);
+ col < ncols && regnum < gdbarch_num_cooked_regs (gdbarch);
regnum++)
{
if (*gdbarch_register_name (gdbarch, regnum) == '\0')
/* Now print the values in hex, 4 or 8 to the row. */
for (col = 0, regnum = start_regnum;
- col < ncols && regnum < gdbarch_num_regs (gdbarch)
- + gdbarch_num_pseudo_regs (gdbarch);
+ col < ncols && regnum < gdbarch_num_cooked_regs (gdbarch);
regnum++)
{
if (*gdbarch_register_name (gdbarch, regnum) == '\0')
/* Do all (or most) registers. */
{
regnum = gdbarch_num_regs (gdbarch);
- while (regnum < gdbarch_num_regs (gdbarch)
- + gdbarch_num_pseudo_regs (gdbarch))
+ while (regnum < gdbarch_num_cooked_regs (gdbarch))
{
if (mips_float_register_p (gdbarch, regnum))
{
mips_single_step_through_delay (struct gdbarch *gdbarch,
struct frame_info *frame)
{
- enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
CORE_ADDR pc = get_frame_pc (frame);
- struct address_space *aspace;
enum mips_isa isa;
ULONGEST insn;
- int status;
int size;
if ((mips_pc_is_mips (pc)
/* _has_delay_slot above will have validated the read. */
insn = mips_fetch_instruction (gdbarch, isa, pc, NULL);
size = mips_insn_size (isa, insn);
- aspace = get_frame_address_space (frame);
+
+ const address_space *aspace = get_frame_address_space (frame);
+
return breakpoint_here_p (aspace, pc + size) != no_breakpoint_here;
}
callable as an sfunc. */
static void
-reinit_frame_cache_sfunc (char *args, int from_tty,
+reinit_frame_cache_sfunc (const char *args, int from_tty,
struct cmd_list_element *c)
{
reinit_frame_cache ();
memaddr &= (info->mach == bfd_mach_mips16
|| info->mach == bfd_mach_mips_micromips) ? ~1 : ~3;
- /* Set the disassembler options. */
- if (!info->disassembler_options)
- /* This string is not recognized explicitly by the disassembler,
- but it tells the disassembler to not try to guess the ABI from
- the bfd elf headers, such that, if the user overrides the ABI
- of a program linked as NewABI, the disassembly will follow the
- register naming conventions specified by the user. */
- info->disassembler_options = "gpr-names=32";
-
return default_print_insn (memaddr, info);
}
-static int
-gdb_print_insn_mips_n32 (bfd_vma memaddr, struct disassemble_info *info)
-{
- /* Set up the disassembler info, so that we get the right
- register names from libopcodes. */
- info->disassembler_options = "gpr-names=n32";
- info->flavour = bfd_target_elf_flavour;
-
- return gdb_print_insn_mips (memaddr, info);
-}
-
-static int
-gdb_print_insn_mips_n64 (bfd_vma memaddr, struct disassemble_info *info)
-{
- /* Set up the disassembler info, so that we get the right
- register names from libopcodes. */
- info->disassembler_options = "gpr-names=64";
- info->flavour = bfd_target_elf_flavour;
-
- return gdb_print_insn_mips (memaddr, info);
-}
-
/* Implement the breakpoint_kind_from_pc gdbarch method. */
static int
msym = lookup_minimal_symbol_by_pc (pc);
if (msym.minsym == NULL
|| BMSYMBOL_VALUE_ADDRESS (msym) != pc
- || MSYMBOL_LINKAGE_NAME (msym.minsym) == NULL
- || !startswith (MSYMBOL_LINKAGE_NAME (msym.minsym), ".pic."))
+ || msym.minsym->linkage_name () == NULL
+ || !startswith (msym.minsym->linkage_name (), ".pic."))
return 0;
/* A two-instruction header. */
mips_find_abi_section (bfd *abfd, asection *sect, void *obj)
{
enum mips_abi *abip = (enum mips_abi *) obj;
- const char *name = bfd_get_section_name (abfd, sect);
+ const char *name = bfd_section_name (sect);
if (*abip != MIPS_ABI_UNKNOWN)
return;
mips_find_long_section (bfd *abfd, asection *sect, void *obj)
{
int *lbp = (int *) obj;
- const char *name = bfd_get_section_name (abfd, sect);
+ const char *name = bfd_section_name (sect);
if (startswith (name, ".gcc_compiled_long32"))
*lbp = 32;
int dspacc;
int dspctl;
- /* Fill in the OS dependent register numbers and names. */
- if (info.osabi == GDB_OSABI_LINUX)
- {
- mips_regnum.fp0 = 38;
- mips_regnum.pc = 37;
- mips_regnum.cause = 36;
- mips_regnum.badvaddr = 35;
- mips_regnum.hi = 34;
- mips_regnum.lo = 33;
- mips_regnum.fp_control_status = 70;
- mips_regnum.fp_implementation_revision = 71;
- mips_regnum.dspacc = -1;
- mips_regnum.dspctl = -1;
- dspacc = 72;
- dspctl = 78;
- num_regs = 90;
- reg_names = mips_linux_reg_names;
- }
- else
- {
- mips_regnum.lo = MIPS_EMBED_LO_REGNUM;
- mips_regnum.hi = MIPS_EMBED_HI_REGNUM;
- mips_regnum.badvaddr = MIPS_EMBED_BADVADDR_REGNUM;
- mips_regnum.cause = MIPS_EMBED_CAUSE_REGNUM;
- mips_regnum.pc = MIPS_EMBED_PC_REGNUM;
- mips_regnum.fp0 = MIPS_EMBED_FP0_REGNUM;
- mips_regnum.fp_control_status = 70;
- mips_regnum.fp_implementation_revision = 71;
- mips_regnum.dspacc = dspacc = -1;
- mips_regnum.dspctl = dspctl = -1;
- num_regs = MIPS_LAST_EMBED_REGNUM + 1;
- if (info.bfd_arch_info != NULL
- && info.bfd_arch_info->mach == bfd_mach_mips3900)
- reg_names = mips_tx39_reg_names;
- else
- reg_names = mips_generic_reg_names;
- }
-
- /* Check any target description for validity. */
- if (tdesc_has_registers (info.target_desc))
- {
- static const char *const mips_gprs[] = {
- "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
- "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
- "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
- "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31"
- };
- static const char *const mips_fprs[] = {
- "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
- "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
- "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
- "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
- };
-
- const struct tdesc_feature *feature;
- int valid_p;
-
- feature = tdesc_find_feature (info.target_desc,
- "org.gnu.gdb.mips.cpu");
- if (feature == NULL)
- return NULL;
-
- tdesc_data = tdesc_data_alloc ();
-
- valid_p = 1;
- for (i = MIPS_ZERO_REGNUM; i <= MIPS_RA_REGNUM; i++)
- valid_p &= tdesc_numbered_register (feature, tdesc_data, i,
- mips_gprs[i]);
-
-
- valid_p &= tdesc_numbered_register (feature, tdesc_data,
- mips_regnum.lo, "lo");
- valid_p &= tdesc_numbered_register (feature, tdesc_data,
- mips_regnum.hi, "hi");
- valid_p &= tdesc_numbered_register (feature, tdesc_data,
- mips_regnum.pc, "pc");
-
- if (!valid_p)
- {
- tdesc_data_cleanup (tdesc_data);
- return NULL;
- }
-
- feature = tdesc_find_feature (info.target_desc,
- "org.gnu.gdb.mips.cp0");
- if (feature == NULL)
- {
- tdesc_data_cleanup (tdesc_data);
- return NULL;
- }
-
- valid_p = 1;
- valid_p &= tdesc_numbered_register (feature, tdesc_data,
- mips_regnum.badvaddr, "badvaddr");
- valid_p &= tdesc_numbered_register (feature, tdesc_data,
- MIPS_PS_REGNUM, "status");
- valid_p &= tdesc_numbered_register (feature, tdesc_data,
- mips_regnum.cause, "cause");
-
- if (!valid_p)
- {
- tdesc_data_cleanup (tdesc_data);
- return NULL;
- }
-
- /* FIXME drow/2007-05-17: The FPU should be optional. The MIPS
- backend is not prepared for that, though. */
- feature = tdesc_find_feature (info.target_desc,
- "org.gnu.gdb.mips.fpu");
- if (feature == NULL)
- {
- tdesc_data_cleanup (tdesc_data);
- return NULL;
- }
-
- valid_p = 1;
- for (i = 0; i < 32; i++)
- valid_p &= tdesc_numbered_register (feature, tdesc_data,
- i + mips_regnum.fp0, mips_fprs[i]);
-
- valid_p &= tdesc_numbered_register (feature, tdesc_data,
- mips_regnum.fp_control_status,
- "fcsr");
- valid_p
- &= tdesc_numbered_register (feature, tdesc_data,
- mips_regnum.fp_implementation_revision,
- "fir");
-
- if (!valid_p)
- {
- tdesc_data_cleanup (tdesc_data);
- return NULL;
- }
-
- num_regs = mips_regnum.fp_implementation_revision + 1;
-
- if (dspacc >= 0)
- {
- feature = tdesc_find_feature (info.target_desc,
- "org.gnu.gdb.mips.dsp");
- /* The DSP registers are optional; it's OK if they are absent. */
- if (feature != NULL)
- {
- i = 0;
- valid_p = 1;
- valid_p &= tdesc_numbered_register (feature, tdesc_data,
- dspacc + i++, "hi1");
- valid_p &= tdesc_numbered_register (feature, tdesc_data,
- dspacc + i++, "lo1");
- valid_p &= tdesc_numbered_register (feature, tdesc_data,
- dspacc + i++, "hi2");
- valid_p &= tdesc_numbered_register (feature, tdesc_data,
- dspacc + i++, "lo2");
- valid_p &= tdesc_numbered_register (feature, tdesc_data,
- dspacc + i++, "hi3");
- valid_p &= tdesc_numbered_register (feature, tdesc_data,
- dspacc + i++, "lo3");
-
- valid_p &= tdesc_numbered_register (feature, tdesc_data,
- dspctl, "dspctl");
-
- if (!valid_p)
- {
- tdesc_data_cleanup (tdesc_data);
- return NULL;
- }
-
- mips_regnum.dspacc = dspacc;
- mips_regnum.dspctl = dspctl;
-
- num_regs = mips_regnum.dspctl + 1;
- }
- }
-
- /* It would be nice to detect an attempt to use a 64-bit ABI
- when only 32-bit registers are provided. */
- reg_names = NULL;
- }
-
/* First of all, extract the elf_flags, if available. */
if (info.abfd && bfd_get_flavour (info.abfd) == bfd_target_elf_flavour)
elf_flags = elf_elfheader (info.abfd)->e_flags;
fprintf_unfiltered (gdb_stdlog, "mips_gdbarch_init: mips_abi = %d\n",
mips_abi);
+ /* Make sure we don't use a 32-bit architecture with a 64-bit ABI. */
+ if (mips_abi != MIPS_ABI_EABI32
+ && mips_abi != MIPS_ABI_O32
+ && info.bfd_arch_info != NULL
+ && info.bfd_arch_info->arch == bfd_arch_mips
+ && info.bfd_arch_info->bits_per_word < 64)
+ info.bfd_arch_info = bfd_lookup_arch (bfd_arch_mips, bfd_mach_mips4000);
+
/* Determine the default compressed ISA. */
if ((elf_flags & EF_MIPS_ARCH_ASE_MICROMIPS) != 0
&& (elf_flags & EF_MIPS_ARCH_ASE_M16) == 0)
&& tdesc_property (info.target_desc, PROPERTY_GP32) != NULL
&& mips_abi != MIPS_ABI_EABI32
&& mips_abi != MIPS_ABI_O32)
+ return NULL;
+
+ /* Fill in the OS dependent register numbers and names. */
+ if (info.osabi == GDB_OSABI_LINUX)
{
- if (tdesc_data != NULL)
- tdesc_data_cleanup (tdesc_data);
- return NULL;
+ mips_regnum.fp0 = 38;
+ mips_regnum.pc = 37;
+ mips_regnum.cause = 36;
+ mips_regnum.badvaddr = 35;
+ mips_regnum.hi = 34;
+ mips_regnum.lo = 33;
+ mips_regnum.fp_control_status = 70;
+ mips_regnum.fp_implementation_revision = 71;
+ mips_regnum.dspacc = -1;
+ mips_regnum.dspctl = -1;
+ dspacc = 72;
+ dspctl = 78;
+ num_regs = 90;
+ reg_names = mips_linux_reg_names;
+ }
+ else
+ {
+ mips_regnum.lo = MIPS_EMBED_LO_REGNUM;
+ mips_regnum.hi = MIPS_EMBED_HI_REGNUM;
+ mips_regnum.badvaddr = MIPS_EMBED_BADVADDR_REGNUM;
+ mips_regnum.cause = MIPS_EMBED_CAUSE_REGNUM;
+ mips_regnum.pc = MIPS_EMBED_PC_REGNUM;
+ mips_regnum.fp0 = MIPS_EMBED_FP0_REGNUM;
+ mips_regnum.fp_control_status = 70;
+ mips_regnum.fp_implementation_revision = 71;
+ mips_regnum.dspacc = dspacc = -1;
+ mips_regnum.dspctl = dspctl = -1;
+ num_regs = MIPS_LAST_EMBED_REGNUM + 1;
+ if (info.bfd_arch_info != NULL
+ && info.bfd_arch_info->mach == bfd_mach_mips3900)
+ reg_names = mips_tx39_reg_names;
+ else
+ reg_names = mips_generic_reg_names;
+ }
+
+ /* Check any target description for validity. */
+ if (tdesc_has_registers (info.target_desc))
+ {
+ static const char *const mips_gprs[] = {
+ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
+ "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
+ "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31"
+ };
+ static const char *const mips_fprs[] = {
+ "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
+ "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
+ "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
+ "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
+ };
+
+ const struct tdesc_feature *feature;
+ int valid_p;
+
+ feature = tdesc_find_feature (info.target_desc,
+ "org.gnu.gdb.mips.cpu");
+ if (feature == NULL)
+ return NULL;
+
+ tdesc_data = tdesc_data_alloc ();
+
+ valid_p = 1;
+ for (i = MIPS_ZERO_REGNUM; i <= MIPS_RA_REGNUM; i++)
+ valid_p &= tdesc_numbered_register (feature, tdesc_data, i,
+ mips_gprs[i]);
+
+
+ valid_p &= tdesc_numbered_register (feature, tdesc_data,
+ mips_regnum.lo, "lo");
+ valid_p &= tdesc_numbered_register (feature, tdesc_data,
+ mips_regnum.hi, "hi");
+ valid_p &= tdesc_numbered_register (feature, tdesc_data,
+ mips_regnum.pc, "pc");
+
+ if (!valid_p)
+ {
+ tdesc_data_cleanup (tdesc_data);
+ return NULL;
+ }
+
+ feature = tdesc_find_feature (info.target_desc,
+ "org.gnu.gdb.mips.cp0");
+ if (feature == NULL)
+ {
+ tdesc_data_cleanup (tdesc_data);
+ return NULL;
+ }
+
+ valid_p = 1;
+ valid_p &= tdesc_numbered_register (feature, tdesc_data,
+ mips_regnum.badvaddr, "badvaddr");
+ valid_p &= tdesc_numbered_register (feature, tdesc_data,
+ MIPS_PS_REGNUM, "status");
+ valid_p &= tdesc_numbered_register (feature, tdesc_data,
+ mips_regnum.cause, "cause");
+
+ if (!valid_p)
+ {
+ tdesc_data_cleanup (tdesc_data);
+ return NULL;
+ }
+
+ /* FIXME drow/2007-05-17: The FPU should be optional. The MIPS
+ backend is not prepared for that, though. */
+ feature = tdesc_find_feature (info.target_desc,
+ "org.gnu.gdb.mips.fpu");
+ if (feature == NULL)
+ {
+ tdesc_data_cleanup (tdesc_data);
+ return NULL;
+ }
+
+ valid_p = 1;
+ for (i = 0; i < 32; i++)
+ valid_p &= tdesc_numbered_register (feature, tdesc_data,
+ i + mips_regnum.fp0, mips_fprs[i]);
+
+ valid_p &= tdesc_numbered_register (feature, tdesc_data,
+ mips_regnum.fp_control_status,
+ "fcsr");
+ valid_p
+ &= tdesc_numbered_register (feature, tdesc_data,
+ mips_regnum.fp_implementation_revision,
+ "fir");
+
+ if (!valid_p)
+ {
+ tdesc_data_cleanup (tdesc_data);
+ return NULL;
+ }
+
+ num_regs = mips_regnum.fp_implementation_revision + 1;
+
+ if (dspacc >= 0)
+ {
+ feature = tdesc_find_feature (info.target_desc,
+ "org.gnu.gdb.mips.dsp");
+ /* The DSP registers are optional; it's OK if they are absent. */
+ if (feature != NULL)
+ {
+ i = 0;
+ valid_p = 1;
+ valid_p &= tdesc_numbered_register (feature, tdesc_data,
+ dspacc + i++, "hi1");
+ valid_p &= tdesc_numbered_register (feature, tdesc_data,
+ dspacc + i++, "lo1");
+ valid_p &= tdesc_numbered_register (feature, tdesc_data,
+ dspacc + i++, "hi2");
+ valid_p &= tdesc_numbered_register (feature, tdesc_data,
+ dspacc + i++, "lo2");
+ valid_p &= tdesc_numbered_register (feature, tdesc_data,
+ dspacc + i++, "hi3");
+ valid_p &= tdesc_numbered_register (feature, tdesc_data,
+ dspacc + i++, "lo3");
+
+ valid_p &= tdesc_numbered_register (feature, tdesc_data,
+ dspctl, "dspctl");
+
+ if (!valid_p)
+ {
+ tdesc_data_cleanup (tdesc_data);
+ return NULL;
+ }
+
+ mips_regnum.dspacc = dspacc;
+ mips_regnum.dspctl = dspctl;
+
+ num_regs = mips_regnum.dspctl + 1;
+ }
+ }
+
+ /* It would be nice to detect an attempt to use a 64-bit ABI
+ when only 32-bit registers are provided. */
+ reg_names = NULL;
}
/* Try to find a pre-existing architecture. */
set_gdbarch_print_registers_info (gdbarch, mips_print_registers_info);
- if (mips_abi == MIPS_ABI_N32)
- set_gdbarch_print_insn (gdbarch, gdb_print_insn_mips_n32);
- else if (mips_abi == MIPS_ABI_N64)
- set_gdbarch_print_insn (gdbarch, gdb_print_insn_mips_n64);
+ set_gdbarch_print_insn (gdbarch, gdb_print_insn_mips);
+ if (mips_abi == MIPS_ABI_N64)
+ set_gdbarch_disassembler_options_implicit
+ (gdbarch, (const char *) mips_disassembler_options_n64);
+ else if (mips_abi == MIPS_ABI_N32)
+ set_gdbarch_disassembler_options_implicit
+ (gdbarch, (const char *) mips_disassembler_options_n32);
else
- set_gdbarch_print_insn (gdbarch, gdb_print_insn_mips);
+ set_gdbarch_disassembler_options_implicit
+ (gdbarch, (const char *) mips_disassembler_options_o32);
+ set_gdbarch_disassembler_options (gdbarch, &mips_disassembler_options);
+ set_gdbarch_valid_disassembler_options (gdbarch,
+ disassembler_options_mips ());
/* FIXME: cagney/2003-08-29: The macros target_have_steppable_watchpoint,
HAVE_NONSTEPPABLE_WATCHPOINT, and target_have_continuable_watchpoint
}
static void
-mips_abi_update (char *ignore_args, int from_tty, struct cmd_list_element *c)
+mips_abi_update (const char *ignore_args,
+ int from_tty, struct cmd_list_element *c)
{
struct gdbarch_info info;
_initialize_mips_tdep (void)
{
static struct cmd_list_element *mipsfpulist = NULL;
- struct cmd_list_element *c;
mips_abi_string = mips_abi_strings[MIPS_ABI_UNKNOWN];
if (MIPS_ABI_LAST + 1
gdbarch_register (bfd_arch_mips, mips_gdbarch_init, mips_dump_tdep);
- mips_pdr_data = register_objfile_data ();
-
/* Create feature sets with the appropriate properties. The values
are not important. */
mips_tdesc_gp32 = allocate_target_description ();