{ "fsr", MIPS_EMBED_FP0_REGNUM + 32 }
};
-/* Some MIPS boards don't support floating point while others only
- support single-precision floating-point operations. */
-
-enum mips_fpu_type
-{
- MIPS_FPU_DOUBLE, /* Full double precision floating point. */
- MIPS_FPU_SINGLE, /* Single precision floating point (R4650). */
- MIPS_FPU_NONE /* No floating point. */
-};
-
#ifndef MIPS_DEFAULT_FPU_TYPE
#define MIPS_DEFAULT_FPU_TYPE MIPS_FPU_DOUBLE
#endif
struct target_desc *mips_tdesc_gp32;
struct target_desc *mips_tdesc_gp64;
-/* MIPS specific per-architecture information */
-struct gdbarch_tdep
-{
- /* from the elf header */
- int elf_flags;
-
- /* mips options */
- enum mips_abi mips_abi;
- enum mips_abi found_abi;
- enum mips_fpu_type mips_fpu_type;
- int mips_last_arg_regnum;
- int mips_last_fp_arg_regnum;
- int default_mask_address_p;
- /* Is the target using 64-bit raw integer registers but only
- storing a left-aligned 32-bit value in each? */
- int mips64_transfers_32bit_regs_p;
- /* Indexes for various registers. IRIX and embedded have
- different values. This contains the "public" fields. Don't
- add any that do not need to be public. */
- 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;
-};
-
const struct mips_regnum *
mips_regnum (struct gdbarch *gdbarch)
{
/* Use pointer types for registers if we can. For n32 we can not,
since we do not have a 64-bit pointer type. */
- if (mips_abi_regsize (gdbarch) == TYPE_LENGTH (builtin_type_void_data_ptr))
+ if (mips_abi_regsize (gdbarch)
+ == TYPE_LENGTH (builtin_type (gdbarch)->builtin_data_ptr))
{
if (rawnum == MIPS_SP_REGNUM || rawnum == MIPS_EMBED_BADVADDR_REGNUM)
- return builtin_type_void_data_ptr;
+ return builtin_type (gdbarch)->builtin_data_ptr;
else if (rawnum == MIPS_EMBED_PC_REGNUM)
- return builtin_type_void_func_ptr;
+ return builtin_type (gdbarch)->builtin_func_ptr;
}
if (mips_abi_regsize (gdbarch) == 4 && TYPE_LENGTH (rawtype) == 8
show_mask_address (struct ui_file *file, int from_tty,
struct cmd_list_element *c, const char *value)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+ struct gdbarch_tdep *tdep = gdbarch_tdep (target_gdbarch);
deprecated_show_value_hack (file, from_tty, c, value);
switch (mask_address_var)
/* Set PC to that address */
pc = get_frame_register_signed (frame, rtype_rs (inst));
break;
+ case 12: /* SYSCALL */
+ {
+ struct gdbarch_tdep *tdep;
+
+ tdep = gdbarch_tdep (get_frame_arch (frame));
+ if (tdep->syscall_next_pc != NULL)
+ pc = tdep->syscall_next_pc (frame);
+ else
+ pc += 4;
+ }
+ break;
default:
pc += 4;
}
/* mips_addr_bits_remove - remove useless address bits */
static CORE_ADDR
-mips_addr_bits_remove (CORE_ADDR addr)
+mips_addr_bits_remove (struct gdbarch *gdbarch, CORE_ADDR addr)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
if (mips_mask_address_p (tdep) && (((ULONGEST) addr) >> 32 == 0xffffffffUL))
/* This hack is a work-around for existing boards using PMON, the
simulator, and any other 64-bit targets that doesn't have true
CORE_ADDR fence;
int instlen;
int seen_adjsp = 0;
+ struct inferior *inf;
pc = gdbarch_addr_bits_remove (gdbarch, pc);
start_pc = pc;
instlen = mips_pc_is_mips16 (pc) ? MIPS_INSN16_SIZE : MIPS_INSN32_SIZE;
+ inf = current_inferior ();
+
/* search back for previous return */
for (start_pc -= instlen;; start_pc -= instlen)
if (start_pc < fence)
stop_soon, but with this test, at least we
don't print out warnings for every child forked (eg, on
decstation). 22apr93 rich@cygnus.com. */
- if (stop_soon == NO_STOP_QUIETLY)
+ if (inf->stop_soon == NO_STOP_QUIETLY)
{
static int blurb_printed = 0;
val = value_contents (arg);
+ /* A 128-bit long double value requires an even-odd pair of
+ floating-point registers. */
+ if (len == 16
+ && fp_register_arg_p (gdbarch, typecode, arg_type)
+ && (float_argreg & 1))
+ {
+ float_argreg++;
+ argreg++;
+ }
+
if (fp_register_arg_p (gdbarch, typecode, arg_type)
&& argreg <= MIPS_LAST_ARG_REGNUM (gdbarch))
{
/* This is a floating point value that fits entirely
- in a single register. */
- LONGEST regval = extract_unsigned_integer (val, len);
+ in a single register or a pair of registers. */
+ int reglen = (len <= MIPS64_REGSIZE ? len : MIPS64_REGSIZE);
+ LONGEST regval = extract_unsigned_integer (val, reglen);
if (mips_debug)
fprintf_unfiltered (gdb_stdlog, " - fpreg=%d val=%s",
- float_argreg, phex (regval, len));
+ float_argreg, phex (regval, reglen));
regcache_cooked_write_unsigned (regcache, float_argreg, regval);
if (mips_debug)
fprintf_unfiltered (gdb_stdlog, " - reg=%d val=%s",
- argreg, phex (regval, len));
+ argreg, phex (regval, reglen));
regcache_cooked_write_unsigned (regcache, argreg, regval);
float_argreg++;
argreg++;
+ if (len == 16)
+ {
+ regval = extract_unsigned_integer (val + reglen, reglen);
+ if (mips_debug)
+ fprintf_unfiltered (gdb_stdlog, " - fpreg=%d val=%s",
+ float_argreg, phex (regval, reglen));
+ regcache_cooked_write_unsigned (regcache, float_argreg, regval);
+
+ if (mips_debug)
+ fprintf_unfiltered (gdb_stdlog, " - reg=%d val=%s",
+ argreg, phex (regval, reglen));
+ regcache_cooked_write_unsigned (regcache, argreg, regval);
+ float_argreg++;
+ argreg++;
+ }
}
else
{
if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
{
if ((typecode == TYPE_CODE_INT
- || typecode == TYPE_CODE_PTR
- || typecode == TYPE_CODE_FLT)
+ || typecode == TYPE_CODE_PTR)
&& len <= 4)
longword_offset = MIPS64_REGSIZE - len;
}
&& (TYPE_CODE (check_typedef (TYPE_FIELD_TYPE (type, 0)))
== TYPE_CODE_FLT)
&& (TYPE_CODE (check_typedef (TYPE_FIELD_TYPE (type, 1)))
- == TYPE_CODE_FLT)))
- && tdep->mips_fpu_type != MIPS_FPU_NONE)
+ == TYPE_CODE_FLT))))
{
/* A struct that contains one or two floats. Each value is part
in the least significant part of their floating point
- register.. */
+ register (or GPR, for soft float). */
int regnum;
int field;
- for (field = 0, regnum = mips_regnum (gdbarch)->fp0;
+ for (field = 0, regnum = (tdep->mips_fpu_type != MIPS_FPU_NONE
+ ? mips_regnum (gdbarch)->fp0
+ : MIPS_V0_REGNUM);
field < TYPE_NFIELDS (type); field++, regnum += 2)
{
int offset = (FIELD_BITPOS (TYPE_FIELDS (type)[field])
if (mips_debug)
fprintf_unfiltered (gdb_stderr, "Return float struct+%d\n",
offset);
- mips_xfer_register (gdbarch, regcache,
- gdbarch_num_regs (gdbarch) + regnum,
- TYPE_LENGTH (TYPE_FIELD_TYPE (type, field)),
- gdbarch_byte_order (gdbarch),
- readbuf, writebuf, offset);
+ if (TYPE_LENGTH (TYPE_FIELD_TYPE (type, field)) == 16)
+ {
+ /* A 16-byte long double field goes in two consecutive
+ registers. */
+ mips_xfer_register (gdbarch, regcache,
+ gdbarch_num_regs (gdbarch) + regnum,
+ 8,
+ gdbarch_byte_order (gdbarch),
+ readbuf, writebuf, offset);
+ mips_xfer_register (gdbarch, regcache,
+ gdbarch_num_regs (gdbarch) + regnum + 1,
+ 8,
+ gdbarch_byte_order (gdbarch),
+ readbuf, writebuf, offset + 8);
+ }
+ else
+ mips_xfer_register (gdbarch, regcache,
+ gdbarch_num_regs (gdbarch) + regnum,
+ TYPE_LENGTH (TYPE_FIELD_TYPE (type, field)),
+ gdbarch_byte_order (gdbarch),
+ readbuf, writebuf, offset);
}
return RETURN_VALUE_REGISTER_CONVENTION;
}
fprintf_unfiltered (gdb_stdlog, " - fpreg=%d val=%s",
float_argreg, phex (regval, len));
regcache_cooked_write_unsigned (regcache, float_argreg++, regval);
- /* CAGNEY: 32 bit MIPS ABI's always reserve two FP
- registers for each argument. The below is (my
- guess) to ensure that the corresponding integer
- register has reserved the same space. */
+ /* Although two FP registers are reserved for each
+ argument, only one corresponding integer register is
+ reserved. */
if (mips_debug)
fprintf_unfiltered (gdb_stdlog, " - reg=%d val=%s",
argreg, phex (regval, len));
- regcache_cooked_write_unsigned (regcache, argreg, regval);
- argreg += 2;
+ regcache_cooked_write_unsigned (regcache, argreg++, regval);
}
/* Reserve space for the FP register. */
stack_offset += align_up (len, MIPS32_REGSIZE);
{
char *fpu;
- if (gdbarch_bfd_arch_info (current_gdbarch)->arch != bfd_arch_mips)
+ if (gdbarch_bfd_arch_info (target_gdbarch)->arch != bfd_arch_mips)
{
printf_unfiltered
("The MIPS floating-point coprocessor is unknown "
return;
}
- switch (MIPS_FPU_TYPE (current_gdbarch))
+ switch (MIPS_FPU_TYPE (target_gdbarch))
{
case MIPS_FPU_SINGLE:
fpu = "single-precision";
void
deprecated_mips_set_processor_regs_hack (void)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+ struct regcache *regcache = get_current_regcache ();
+ struct gdbarch *gdbarch = get_regcache_arch (regcache);
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
ULONGEST prid;
- regcache_cooked_read_unsigned (get_current_regcache (),
- MIPS_PRID_REGNUM, &prid);
+ regcache_cooked_read_unsigned (regcache, MIPS_PRID_REGNUM, &prid);
if ((prid & ~0xf) == 0x700)
tdep->mips_processor_reg_names = mips_r3041_reg_names;
}
static int
gdb_print_insn_mips (bfd_vma memaddr, struct disassemble_info *info)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
-
/* FIXME: cagney/2003-06-26: Is this even necessary? The
disassembler needs to be able to locally determine the ISA, and
not rely on GDB. Otherwize the stand-alone 'objdump -d' will not
memaddr &= (info->mach == bfd_mach_mips16 ? ~1 : ~3);
/* Set the disassembler options. */
- if (tdep->mips_abi == MIPS_ABI_N32 || tdep->mips_abi == MIPS_ABI_N64)
- {
- /* Set up the disassembler info, so that we get the right
- register names from libopcodes. */
- if (tdep->mips_abi == MIPS_ABI_N32)
- info->disassembler_options = "gpr-names=n32";
- else
- info->disassembler_options = "gpr-names=64";
- info->flavour = bfd_target_elf_flavour;
- }
- else
+ 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
return print_insn_little_mips (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);
+}
+
/* This function implements gdbarch_breakpoint_from_pc. It uses the program
counter value to determine whether a 16- or 32-bit breakpoint should be used.
It returns a pointer to a string of bytes that encode a breakpoint
set_gdbarch_print_registers_info (gdbarch, mips_print_registers_info);
- set_gdbarch_print_insn (gdbarch, gdb_print_insn_mips);
+ 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);
+ else
+ set_gdbarch_print_insn (gdbarch, gdb_print_insn_mips);
/* FIXME: cagney/2003-08-29: The macros HAVE_STEPPABLE_WATCHPOINT,
HAVE_NONSTEPPABLE_WATCHPOINT, and HAVE_CONTINUABLE_WATCHPOINT
struct cmd_list_element *ignored_cmd,
const char *ignored_value)
{
- if (gdbarch_bfd_arch_info (current_gdbarch)->arch != bfd_arch_mips)
+ if (gdbarch_bfd_arch_info (target_gdbarch)->arch != bfd_arch_mips)
fprintf_filtered
(file,
"The MIPS ABI is unknown because the current architecture "
else
{
enum mips_abi global_abi = global_mips_abi ();
- enum mips_abi actual_abi = mips_abi (current_gdbarch);
+ enum mips_abi actual_abi = mips_abi (target_gdbarch);
const char *actual_abi_str = mips_abi_strings[actual_abi];
if (global_abi == MIPS_ABI_UNKNOWN)